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 40205ed6bfSAndreas Jaekel static int verbose = 0; 4116ff6b2fSAndreas Jaekel static int grep_friendly = 0; 4216ff6b2fSAndreas Jaekel 4316ff6b2fSAndreas Jaekel static void 4416ff6b2fSAndreas Jaekel zpf(char *fmt, ...) 4516ff6b2fSAndreas Jaekel { 4616ff6b2fSAndreas Jaekel va_list ap; 4716ff6b2fSAndreas Jaekel 4816ff6b2fSAndreas Jaekel va_start(ap, fmt); 4916ff6b2fSAndreas Jaekel vprintf(fmt, ap); 5016ff6b2fSAndreas Jaekel va_end(ap); 5116ff6b2fSAndreas Jaekel if (grep_friendly) { 5216ff6b2fSAndreas Jaekel printf(" "); 5316ff6b2fSAndreas Jaekel } else { 5416ff6b2fSAndreas Jaekel printf("\n"); 5516ff6b2fSAndreas Jaekel } 5616ff6b2fSAndreas Jaekel } 5716ff6b2fSAndreas Jaekel 5816ff6b2fSAndreas Jaekel static void 5916ff6b2fSAndreas Jaekel znl(void) 6016ff6b2fSAndreas Jaekel { 6116ff6b2fSAndreas Jaekel if (grep_friendly) 6216ff6b2fSAndreas Jaekel printf("\n"); 6316ff6b2fSAndreas Jaekel } 64205ed6bfSAndreas Jaekel 65*2eabeab5SAndreas Jaekel static void 66*2eabeab5SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex) 67*2eabeab5SAndreas Jaekel { 68*2eabeab5SAndreas Jaekel int i; 69*2eabeab5SAndreas Jaekel 70*2eabeab5SAndreas Jaekel for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 71*2eabeab5SAndreas Jaekel sprintf(hex + 2 * i, "%02x", sig[i]); 72*2eabeab5SAndreas Jaekel } 73*2eabeab5SAndreas Jaekel hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 74*2eabeab5SAndreas Jaekel } 75*2eabeab5SAndreas Jaekel 76add9520fSAndreas Jaekel static int 77a18c35b9SAndreas Jaekel zev_statistics(int fd) 78a18c35b9SAndreas Jaekel { 79a18c35b9SAndreas Jaekel zev_statistics_t zs; 80add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 81a18c35b9SAndreas Jaekel perror("getting statistics data failed"); 82add9520fSAndreas Jaekel return (EXIT_FAILURE); 83a18c35b9SAndreas Jaekel } 84a18c35b9SAndreas Jaekel printf("ZEV module state:\n"); 85a18c35b9SAndreas Jaekel 86a18c35b9SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 87a18c35b9SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 88a18c35b9SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 89a18c35b9SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 90a18c35b9SAndreas Jaekel 91add9520fSAndreas Jaekel printf(" discarded events : %lu\n", 92add9520fSAndreas Jaekel zs.zev_cnt_discarded_events); 93add9520fSAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 94add9520fSAndreas Jaekel 95a18c35b9SAndreas Jaekel printf("ZFS event statistics:\n"); 96a18c35b9SAndreas Jaekel 97a18c35b9SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 98a18c35b9SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 99a18c35b9SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 100a18c35b9SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 101a18c35b9SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 102a18c35b9SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 103a18c35b9SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 104a18c35b9SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 105a18c35b9SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 106a18c35b9SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 107a18c35b9SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 108a18c35b9SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 109a18c35b9SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 110a18c35b9SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 111a18c35b9SAndreas Jaekel zs.zev_cnt_znode_truncate); 112a18c35b9SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 113a18c35b9SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 114add9520fSAndreas Jaekel return EXIT_SUCCESS; 115a18c35b9SAndreas Jaekel } 116a18c35b9SAndreas Jaekel 117a18c35b9SAndreas Jaekel static void 11816ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info) 11916ff6b2fSAndreas Jaekel { 12016ff6b2fSAndreas Jaekel zpf(" %s.inode: %llu", name, info->ino); 12116ff6b2fSAndreas Jaekel zpf(" %s.gen: %llu", name, info->gen); 12216ff6b2fSAndreas Jaekel zpf(" %s.mtime: %llu", name, info->mtime); 12316ff6b2fSAndreas Jaekel zpf(" %s.ctime: %llu", name, info->ctime); 12416ff6b2fSAndreas Jaekel zpf(" %s.size: %llu", name, info->size); 12516ff6b2fSAndreas Jaekel zpf(" %s.mode: %llo", name, info->mode); 12616ff6b2fSAndreas Jaekel zpf(" %s.links: %llu", name, info->links); 12716ff6b2fSAndreas Jaekel zpf(" %s.type: %lu", name, info->type); 12816ff6b2fSAndreas Jaekel zpf(" %s.flags: %lu", name, info->flags); 12916ff6b2fSAndreas Jaekel } 13016ff6b2fSAndreas Jaekel 13116ff6b2fSAndreas Jaekel static void 13216ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec) 13316ff6b2fSAndreas Jaekel { 13416ff6b2fSAndreas Jaekel int i; 13516ff6b2fSAndreas Jaekel int j; 13616ff6b2fSAndreas Jaekel uint8_t *p; 13716ff6b2fSAndreas Jaekel char c; 13816ff6b2fSAndreas Jaekel 13916ff6b2fSAndreas Jaekel zpf(" payload:"); 14016ff6b2fSAndreas Jaekel p = (uint8_t *)ZEV_PAYLOAD(rec); 14116ff6b2fSAndreas Jaekel for (i=0; i<rec->payload_len; i+=16) { 14216ff6b2fSAndreas Jaekel printf(" "); 14316ff6b2fSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 14416ff6b2fSAndreas Jaekel printf("%02x ", p[j]); 14516ff6b2fSAndreas Jaekel if (j == i + 7) 14616ff6b2fSAndreas Jaekel printf(" "); 14716ff6b2fSAndreas Jaekel } 14816ff6b2fSAndreas Jaekel if (grep_friendly) 14916ff6b2fSAndreas Jaekel continue; 15016ff6b2fSAndreas Jaekel for (; j<i+16; j++) { 15116ff6b2fSAndreas Jaekel printf(" "); 15216ff6b2fSAndreas Jaekel if (j == i + 7) 15316ff6b2fSAndreas Jaekel printf(" "); 15416ff6b2fSAndreas Jaekel } 15516ff6b2fSAndreas Jaekel printf(" "); 15616ff6b2fSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 15716ff6b2fSAndreas Jaekel c = '.'; 15816ff6b2fSAndreas Jaekel if (p[j] >= ' ' && p[j] <= '~') 15916ff6b2fSAndreas Jaekel c = p[j]; 16016ff6b2fSAndreas Jaekel printf("%c", c); 16116ff6b2fSAndreas Jaekel if (j == i + 7) 16216ff6b2fSAndreas Jaekel printf(" "); 16316ff6b2fSAndreas Jaekel } 16416ff6b2fSAndreas Jaekel printf("\n"); 16516ff6b2fSAndreas Jaekel } 16616ff6b2fSAndreas Jaekel } 16716ff6b2fSAndreas Jaekel 16816ff6b2fSAndreas Jaekel static void 169f2dd45e5SAndreas Jaekel zev_print_error(char *buf) 170f2dd45e5SAndreas Jaekel { 171f2dd45e5SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 172f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 173f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 174f2dd45e5SAndreas Jaekel 17516ff6b2fSAndreas Jaekel if (verbose) { 17616ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 17716ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 17816ff6b2fSAndreas Jaekel zpf(" failed.op: %s", 17916ff6b2fSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN]); 18016ff6b2fSAndreas Jaekel zpf(" message: %s", ZEV_ERRSTR(rec)); 18116ff6b2fSAndreas Jaekel znl(); 18216ff6b2fSAndreas Jaekel } else { 183f2dd45e5SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 184f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 18516ff6b2fSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], 18616ff6b2fSAndreas Jaekel ZEV_ERRSTR(rec)); 18716ff6b2fSAndreas Jaekel } 188f2dd45e5SAndreas Jaekel } 189f2dd45e5SAndreas Jaekel 190f2dd45e5SAndreas Jaekel static void 191888fea18SAndreas Jaekel zev_print_mark(char *buf) 192888fea18SAndreas Jaekel { 193888fea18SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 194888fea18SAndreas Jaekel time_t op_time = rec->op_time; 195888fea18SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 196888fea18SAndreas Jaekel 19716ff6b2fSAndreas Jaekel if (verbose) { 19816ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 19916ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 20016ff6b2fSAndreas Jaekel zpf(" mark.id: %llu", rec->mark_id); 20116ff6b2fSAndreas Jaekel zpf(" payload.len: %llu", rec->payload_len); 20216ff6b2fSAndreas Jaekel if (rec->payload_len) 20316ff6b2fSAndreas Jaekel zev_print_mark_payload(rec); 20416ff6b2fSAndreas Jaekel znl(); 20516ff6b2fSAndreas Jaekel } else { 206888fea18SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 20716ff6b2fSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 20816ff6b2fSAndreas Jaekel rec->mark_id, rec->payload_len); 20916ff6b2fSAndreas Jaekel } 210888fea18SAndreas Jaekel } 211888fea18SAndreas Jaekel 212888fea18SAndreas Jaekel static void 213f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf) 214f2dd45e5SAndreas Jaekel { 215f2dd45e5SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 216f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 217f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 218f2dd45e5SAndreas Jaekel 21916ff6b2fSAndreas Jaekel if (verbose) { 22016ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 22116ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 22216ff6b2fSAndreas Jaekel zpf(" dataset: %s", ZEV_DATASET(rec)); 22316ff6b2fSAndreas Jaekel zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 22416ff6b2fSAndreas Jaekel zpf(" remount: %s", rec->remount ? "true" : "false"); 22516ff6b2fSAndreas Jaekel zev_print_inode_info("root", &rec->root); 22616ff6b2fSAndreas Jaekel znl(); 22716ff6b2fSAndreas Jaekel } else { 22816ff6b2fSAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' " 22916ff6b2fSAndreas Jaekel "mountpoint='%s'\n", 230f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 231f2dd45e5SAndreas Jaekel rec->guid, 232f2dd45e5SAndreas Jaekel rec->remount ? "true" : "false", 233f2dd45e5SAndreas Jaekel ZEV_DATASET(rec), 234f2dd45e5SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 235f2dd45e5SAndreas Jaekel } 23616ff6b2fSAndreas Jaekel } 237f2dd45e5SAndreas Jaekel 238f2dd45e5SAndreas Jaekel static void 239f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf) 240f2dd45e5SAndreas Jaekel { 241f2dd45e5SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 242f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 243f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 244f2dd45e5SAndreas Jaekel 24516ff6b2fSAndreas Jaekel if (verbose) { 24616ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 24716ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 24816ff6b2fSAndreas Jaekel znl(); 24916ff6b2fSAndreas Jaekel } else { 250f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu\n", 251f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 252f2dd45e5SAndreas Jaekel rec->guid); 253f2dd45e5SAndreas Jaekel } 25416ff6b2fSAndreas Jaekel } 255f2dd45e5SAndreas Jaekel 256f2dd45e5SAndreas Jaekel static void 257f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf) 258f2dd45e5SAndreas Jaekel { 259f2dd45e5SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_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); 26612119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 26716ff6b2fSAndreas Jaekel zpf(" offset: %llu", rec->offset); 26816ff6b2fSAndreas Jaekel zpf(" length: %llu", rec->length); 26916ff6b2fSAndreas Jaekel znl(); 27016ff6b2fSAndreas Jaekel } else { 271f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 272f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 273f2dd45e5SAndreas Jaekel rec->guid, 274f2dd45e5SAndreas Jaekel rec->offset, 275f2dd45e5SAndreas Jaekel rec->length); 276f2dd45e5SAndreas Jaekel } 27716ff6b2fSAndreas Jaekel } 278f2dd45e5SAndreas Jaekel 279f2dd45e5SAndreas Jaekel static void 280f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf) 281f2dd45e5SAndreas Jaekel { 282f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 283f2dd45e5SAndreas Jaekel } 284f2dd45e5SAndreas Jaekel 285f2dd45e5SAndreas Jaekel static void 286f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 287f2dd45e5SAndreas Jaekel { 288f2dd45e5SAndreas Jaekel zev_znode_close_after_update_t *rec = 289f2dd45e5SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 290f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 291f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 292f2dd45e5SAndreas Jaekel 29316ff6b2fSAndreas Jaekel if (verbose) { 29416ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 29516ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 29616ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 29716ff6b2fSAndreas Jaekel znl(); 29816ff6b2fSAndreas Jaekel } else { 299f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 300f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 301f2dd45e5SAndreas Jaekel rec->guid, 302f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen); 303f2dd45e5SAndreas Jaekel } 30416ff6b2fSAndreas Jaekel } 305f2dd45e5SAndreas Jaekel 306f2dd45e5SAndreas Jaekel static void 307f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf) 308f2dd45e5SAndreas Jaekel { 309f2dd45e5SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 310f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 311f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 312*2eabeab5SAndreas Jaekel zev_sig_t *sig; 313*2eabeab5SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 314f2dd45e5SAndreas Jaekel 31516ff6b2fSAndreas Jaekel if (verbose) { 31616ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 31716ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 31812119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 31916ff6b2fSAndreas Jaekel zpf(" name: '%s'", ZEV_NAME(rec)); 320*2eabeab5SAndreas Jaekel sig = &rec->signature; 321*2eabeab5SAndreas Jaekel sig2hex_direct(sig->value, sigval); 322*2eabeab5SAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 323*2eabeab5SAndreas Jaekel sig->level, sig->block_offset, sigval); 32416ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 32512119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 32616ff6b2fSAndreas Jaekel znl(); 32716ff6b2fSAndreas Jaekel } else { 32835d4e8ddSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 32935d4e8ddSAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 330f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 331f2dd45e5SAndreas Jaekel rec->guid, 332f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 333f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 33435d4e8ddSAndreas Jaekel rec->file.mtime, rec->parent.mtime, 335f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 336f2dd45e5SAndreas Jaekel } 33716ff6b2fSAndreas Jaekel } 338f2dd45e5SAndreas Jaekel 339f2dd45e5SAndreas Jaekel static void 340f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf) 341f2dd45e5SAndreas Jaekel { 342f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 343f2dd45e5SAndreas Jaekel } 344f2dd45e5SAndreas Jaekel 345f2dd45e5SAndreas Jaekel static void 346f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 347f2dd45e5SAndreas Jaekel { 348f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 349f2dd45e5SAndreas Jaekel } 350f2dd45e5SAndreas Jaekel 351f2dd45e5SAndreas Jaekel static void 352f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf) 353f2dd45e5SAndreas Jaekel { 354f2dd45e5SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 355f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 356f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 357f2dd45e5SAndreas Jaekel 35816ff6b2fSAndreas Jaekel if (verbose) { 35916ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 36016ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 36112119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 36216ff6b2fSAndreas Jaekel zpf(" file.name: '%s'", ZEV_NAME(rec)); 36316ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 36412119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 36516ff6b2fSAndreas Jaekel znl(); 36616ff6b2fSAndreas Jaekel } else { 36716ff6b2fSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu " 36816ff6b2fSAndreas Jaekel "file.mtime=%llu name='%s'\n", 369f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 370f2dd45e5SAndreas Jaekel rec->guid, 371f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 37297dcf88dSAndreas Jaekel rec->file.mtime, 373f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 374f2dd45e5SAndreas Jaekel } 37516ff6b2fSAndreas Jaekel } 376f2dd45e5SAndreas Jaekel 377f2dd45e5SAndreas Jaekel static void 378f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf) 379f2dd45e5SAndreas Jaekel { 380f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 381f2dd45e5SAndreas Jaekel } 382f2dd45e5SAndreas Jaekel 383f2dd45e5SAndreas Jaekel static void 384f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf) 385f2dd45e5SAndreas Jaekel { 386f2dd45e5SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 387f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 388f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 389f2dd45e5SAndreas Jaekel 39016ff6b2fSAndreas Jaekel if (verbose) { 39116ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 39216ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 39312119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 39416ff6b2fSAndreas Jaekel zpf(" link.name: '%s'", ZEV_NAME(rec)); 39516ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 39612119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 39716ff6b2fSAndreas Jaekel znl(); 39816ff6b2fSAndreas Jaekel } else { 399a01b300aSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 400a01b300aSAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 401f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 402f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 403f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 404a01b300aSAndreas Jaekel rec->file.ctime, rec->parent.ctime, 405f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 40616ff6b2fSAndreas Jaekel } 407f2dd45e5SAndreas Jaekel } 408f2dd45e5SAndreas Jaekel 409f2dd45e5SAndreas Jaekel static void 410f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf) 411f2dd45e5SAndreas Jaekel { 412f2dd45e5SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 413f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 414f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 415*2eabeab5SAndreas Jaekel zev_sig_t *sig; 416*2eabeab5SAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 417f2dd45e5SAndreas Jaekel 41816ff6b2fSAndreas Jaekel if (verbose) { 41916ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 42016ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 42112119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 42216ff6b2fSAndreas Jaekel zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 42316ff6b2fSAndreas Jaekel zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 424*2eabeab5SAndreas Jaekel sig = &rec->signature; 425*2eabeab5SAndreas Jaekel sig2hex_direct(sig->value, sigval); 426*2eabeab5SAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 427*2eabeab5SAndreas Jaekel sig->level, sig->block_offset, sigval); 42816ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 42912119a7eSAndreas Jaekel zev_print_inode_info("parent", &rec->parent); 43016ff6b2fSAndreas Jaekel znl(); 43116ff6b2fSAndreas Jaekel } else { 43216ff6b2fSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 43316ff6b2fSAndreas Jaekel "name='%s' link='%s'\n", 434f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 435f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 436f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 437f2dd45e5SAndreas Jaekel ZEV_NAME(rec), 438f2dd45e5SAndreas Jaekel ZEV_LINK(rec)); 439f2dd45e5SAndreas Jaekel } 44016ff6b2fSAndreas Jaekel } 441f2dd45e5SAndreas Jaekel 442f2dd45e5SAndreas Jaekel static void 443f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf) 444f2dd45e5SAndreas Jaekel { 445f2dd45e5SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 446f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 447f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 448f2dd45e5SAndreas Jaekel 44916ff6b2fSAndreas Jaekel if (verbose) { 45016ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 45116ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 45212119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 45316ff6b2fSAndreas Jaekel zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 45416ff6b2fSAndreas Jaekel zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 45516ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 45616ff6b2fSAndreas Jaekel zev_print_inode_info("srcdir", &rec->srcdir); 45716ff6b2fSAndreas Jaekel zev_print_inode_info("dstdir", &rec->dstdir); 45816ff6b2fSAndreas Jaekel znl(); 45916ff6b2fSAndreas Jaekel } else { 46016ff6b2fSAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 46116ff6b2fSAndreas Jaekel "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 46216ff6b2fSAndreas Jaekel "srcdir.mtime=%llu, srcdir.ctime=%llu, " 46316ff6b2fSAndreas Jaekel "dstdir.mtime=%llu, dstdir.ctime=%llu, " 464f2dd45e5SAndreas Jaekel "srcname='%s' dstname='%s'\n", 465f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 466f2dd45e5SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 467f2dd45e5SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 468f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 46935d4e8ddSAndreas Jaekel rec->file.mtime, rec->file.ctime, 47035d4e8ddSAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 47135d4e8ddSAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 472f2dd45e5SAndreas Jaekel ZEV_SRCNAME(rec), 473f2dd45e5SAndreas Jaekel ZEV_DSTNAME(rec)); 474f2dd45e5SAndreas Jaekel } 47516ff6b2fSAndreas Jaekel } 476f2dd45e5SAndreas Jaekel 477f2dd45e5SAndreas Jaekel static void 478f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf) 479f2dd45e5SAndreas Jaekel { 480f2dd45e5SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 481f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 482f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 483205ed6bfSAndreas Jaekel zev_sig_t *sig; 484205ed6bfSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 485205ed6bfSAndreas Jaekel int i; 486f2dd45e5SAndreas Jaekel 487205ed6bfSAndreas Jaekel if (verbose) { 48816ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 48916ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 49012119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 49116ff6b2fSAndreas Jaekel zpf(" offset: %llu", rec->offset); 49216ff6b2fSAndreas Jaekel zpf(" length: %llu", rec->length); 49316ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 49416ff6b2fSAndreas Jaekel znl(); 495205ed6bfSAndreas Jaekel for (i=0; i<rec->signature_cnt; i++) { 496205ed6bfSAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 497205ed6bfSAndreas Jaekel sig += i; 498205ed6bfSAndreas Jaekel sig2hex_direct(sig->value, sigval); 499*2eabeab5SAndreas Jaekel zpf(" sig: level %d, offset %llu, value %s", 500205ed6bfSAndreas Jaekel sig->level, sig->block_offset, sigval); 501205ed6bfSAndreas Jaekel } 50216ff6b2fSAndreas Jaekel } else { 50316ff6b2fSAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 50416ff6b2fSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 50516ff6b2fSAndreas Jaekel rec->file.ino, rec->file.gen, 50616ff6b2fSAndreas Jaekel rec->offset, rec->length); 507205ed6bfSAndreas Jaekel } 508f2dd45e5SAndreas Jaekel } 509f2dd45e5SAndreas Jaekel 510f2dd45e5SAndreas Jaekel static void 511f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf) 512f2dd45e5SAndreas Jaekel { 513f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 514f2dd45e5SAndreas Jaekel } 515f2dd45e5SAndreas Jaekel 516f2dd45e5SAndreas Jaekel static void 517f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf) 518f2dd45e5SAndreas Jaekel { 519f2dd45e5SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 520f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 521f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 522f2dd45e5SAndreas Jaekel 52316ff6b2fSAndreas Jaekel if (verbose) { 52416ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 52516ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 52612119a7eSAndreas Jaekel zpf(" txg: %llu", rec->txg); 52716ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 52816ff6b2fSAndreas Jaekel znl(); 52916ff6b2fSAndreas Jaekel } else { 53035d4e8ddSAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 531f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 53235d4e8ddSAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 533f2dd45e5SAndreas Jaekel } 53416ff6b2fSAndreas Jaekel } 535f2dd45e5SAndreas Jaekel 536f2dd45e5SAndreas Jaekel static void 537f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf) 538f2dd45e5SAndreas Jaekel { 539f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 540f2dd45e5SAndreas Jaekel } 541f2dd45e5SAndreas Jaekel 542f2dd45e5SAndreas Jaekel static void 543aafc540fSAndreas Jaekel zev_print_event(char *buf, int len) 544aafc540fSAndreas Jaekel { 545f2dd45e5SAndreas Jaekel int record_len; 546f2dd45e5SAndreas Jaekel int op; 547aafc540fSAndreas Jaekel 548f2dd45e5SAndreas Jaekel record_len = *(uint32_t *)buf; 549f2dd45e5SAndreas Jaekel if (record_len != len) { 550f2dd45e5SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 551f2dd45e5SAndreas Jaekel record_len, len); 552aafc540fSAndreas Jaekel exit(1); 553aafc540fSAndreas Jaekel } 554f2dd45e5SAndreas Jaekel op = *((uint32_t *)buf + 1); 555aafc540fSAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 556f2dd45e5SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 557aafc540fSAndreas Jaekel exit(1); 558aafc540fSAndreas Jaekel } 559f2dd45e5SAndreas Jaekel switch (op) { 560f2dd45e5SAndreas Jaekel case ZEV_OP_ERROR: 561f2dd45e5SAndreas Jaekel zev_print_error(buf); 562aafc540fSAndreas Jaekel break; 563888fea18SAndreas Jaekel case ZEV_OP_MARK: 564888fea18SAndreas Jaekel zev_print_mark(buf); 565888fea18SAndreas Jaekel break; 566f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 567f2dd45e5SAndreas Jaekel zev_print_zfs_mount(buf); 568aafc540fSAndreas Jaekel break; 569f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 570f2dd45e5SAndreas Jaekel zev_print_zfs_umount(buf); 571aafc540fSAndreas Jaekel break; 572f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 573f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 574aafc540fSAndreas Jaekel break; 575f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 576f2dd45e5SAndreas Jaekel zev_print_zvol_write(buf); 577f2dd45e5SAndreas Jaekel break; 578f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 579f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(buf); 580f2dd45e5SAndreas Jaekel break; 581f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 582f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 583f2dd45e5SAndreas Jaekel break; 584f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 585f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(buf); 586f2dd45e5SAndreas Jaekel break; 587f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 588f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 589f2dd45e5SAndreas Jaekel break; 590f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 591f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 592f2dd45e5SAndreas Jaekel break; 593f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 594f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(buf); 595f2dd45e5SAndreas Jaekel break; 596f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 597f2dd45e5SAndreas Jaekel zev_print_znode_link(buf); 598f2dd45e5SAndreas Jaekel break; 599f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 600f2dd45e5SAndreas Jaekel zev_print_znode_symlink(buf); 601f2dd45e5SAndreas Jaekel break; 602f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 603f2dd45e5SAndreas Jaekel zev_print_znode_rename(buf); 604f2dd45e5SAndreas Jaekel break; 605f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 606f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 607f2dd45e5SAndreas Jaekel break; 608f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 609f2dd45e5SAndreas Jaekel zev_print_znode_truncate(buf); 610f2dd45e5SAndreas Jaekel break; 611f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 612f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 613f2dd45e5SAndreas Jaekel break; 614f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 615f2dd45e5SAndreas Jaekel zev_print_znode_acl(buf); 616aafc540fSAndreas Jaekel break; 617aafc540fSAndreas Jaekel default: 618f2dd45e5SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 619aafc540fSAndreas Jaekel exit(1); 620aafc540fSAndreas Jaekel } 621aafc540fSAndreas Jaekel } 622aafc540fSAndreas Jaekel 623add9520fSAndreas Jaekel static int 6246a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 625a18c35b9SAndreas Jaekel { 626a18c35b9SAndreas Jaekel struct pollfd pfd[1]; 627a18c35b9SAndreas Jaekel int ret; 628aafc540fSAndreas Jaekel char buf[4096]; 629d979f56cSAndreas Jaekel zev_event_t *ev; 630d979f56cSAndreas Jaekel int off = 0; 631add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 632add9520fSAndreas Jaekel int q_fd; 633add9520fSAndreas Jaekel 6346a6a51eeSAndreas Jaekel if (create_tmp_queue) { 635add9520fSAndreas Jaekel aq.zev_max_queue_len = 0; 636add9520fSAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 637add9520fSAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 638add9520fSAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 639add9520fSAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 640add9520fSAndreas Jaekel 641add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 642add9520fSAndreas Jaekel perror("adding temporary queue failed"); 643add9520fSAndreas Jaekel return (EXIT_FAILURE); 644add9520fSAndreas Jaekel } 645add9520fSAndreas Jaekel 6466a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 6476a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 648add9520fSAndreas Jaekel q_fd = open(buf, O_RDONLY); 649add9520fSAndreas Jaekel if (q_fd < 0) { 650add9520fSAndreas Jaekel perror("opening queue device failed"); 651add9520fSAndreas Jaekel return (EXIT_FAILURE); 652add9520fSAndreas Jaekel } 6536a6a51eeSAndreas Jaekel } else { 6546a6a51eeSAndreas Jaekel q_fd = fd; 6556a6a51eeSAndreas Jaekel } 656add9520fSAndreas Jaekel 657a18c35b9SAndreas Jaekel while (1) { 658add9520fSAndreas Jaekel pfd[0].fd = q_fd; 659a18c35b9SAndreas Jaekel pfd[0].events = POLLIN; 660a18c35b9SAndreas Jaekel ret = poll(pfd, 1, 1000); 661a18c35b9SAndreas Jaekel if (ret < 0) { 662a18c35b9SAndreas Jaekel perror("poll failed"); 6636a6a51eeSAndreas Jaekel close(q_fd); 664add9520fSAndreas Jaekel return(EXIT_FAILURE); 665a18c35b9SAndreas Jaekel } 666a18c35b9SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 667a18c35b9SAndreas Jaekel continue; 668a18c35b9SAndreas Jaekel /* data available */ 669add9520fSAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 670a18c35b9SAndreas Jaekel if (ret < 0) { 671a18c35b9SAndreas Jaekel perror("read failed"); 6726a6a51eeSAndreas Jaekel close(q_fd); 673add9520fSAndreas Jaekel return(EXIT_FAILURE); 674a18c35b9SAndreas Jaekel } 675a18c35b9SAndreas Jaekel if (ret == 0) 676a18c35b9SAndreas Jaekel continue; 677d979f56cSAndreas Jaekel while (ret > off) { 678d979f56cSAndreas Jaekel ev = (zev_event_t *)(buf + off); 679d979f56cSAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 680d979f56cSAndreas Jaekel off += ev->header.record_len; 681d979f56cSAndreas Jaekel } 682149d0affSAndreas Jaekel off = 0; 683a18c35b9SAndreas Jaekel } 6846a6a51eeSAndreas Jaekel if (create_tmp_queue) 685add9520fSAndreas Jaekel close(q_fd); 686add9520fSAndreas Jaekel return EXIT_SUCCESS; 687a18c35b9SAndreas Jaekel } 688a18c35b9SAndreas Jaekel 689a18c35b9SAndreas Jaekel static void 690a18c35b9SAndreas Jaekel usage(char *progname) 691a18c35b9SAndreas Jaekel { 692add9520fSAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 693add9520fSAndreas Jaekel fprintf(stderr, "\n"); 694add9520fSAndreas Jaekel fprintf(stderr, " Status information:\n"); 695a18c35b9SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 696a18c35b9SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 697add9520fSAndreas Jaekel fprintf(stderr, " -D print zev module debug " 698add9520fSAndreas Jaekel "information\n"); 699add9520fSAndreas Jaekel fprintf(stderr, "\n"); 700add9520fSAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 701add9520fSAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 702add9520fSAndreas Jaekel "length\n"); 703add9520fSAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 704add9520fSAndreas Jaekel "this pool\n"); 705a18c35b9SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 706add9520fSAndreas Jaekel fprintf(stderr, "\n"); 707add9520fSAndreas Jaekel fprintf(stderr, " Queue management:\n"); 708add9520fSAndreas Jaekel fprintf(stderr, " -l list queues\n"); 7096a6a51eeSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 7106a6a51eeSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 711add9520fSAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 712add9520fSAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 713add9520fSAndreas Jaekel "(default)\n"); 714add9520fSAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 715add9520fSAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 7166a6a51eeSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 717add9520fSAndreas Jaekel "length\n"); 718add9520fSAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 719add9520fSAndreas Jaekel "throttle\n"); 720add9520fSAndreas Jaekel fprintf(stderr, "\n"); 721add9520fSAndreas Jaekel fprintf(stderr, " Other options:\n"); 722add9520fSAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 723add9520fSAndreas Jaekel "('%s')\n", ZEV_DEVICE); 7246a6a51eeSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 7256a6a51eeSAndreas Jaekel "queue name\n"); 726888fea18SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 72742110aacSAndreas Jaekel fprintf(stderr, " -c <filename> list file's content " 72842110aacSAndreas Jaekel "checksums\n"); 72916ff6b2fSAndreas Jaekel fprintf(stderr, " -v verbose: additional output " 730205ed6bfSAndreas Jaekel "for some operations\n"); 73116ff6b2fSAndreas Jaekel fprintf(stderr, " -g grep-friendly event output, " 73216ff6b2fSAndreas Jaekel "one event per line\n"); 733a18c35b9SAndreas Jaekel exit (EXIT_FAILURE); 734a18c35b9SAndreas Jaekel } 735a18c35b9SAndreas Jaekel 736a18c35b9SAndreas Jaekel static int 7376a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 738a18c35b9SAndreas Jaekel { 739add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 740add9520fSAndreas Jaekel int namelen; 741a18c35b9SAndreas Jaekel 742add9520fSAndreas Jaekel namelen = strlen(arg); 743add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 744add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 745a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 746a18c35b9SAndreas Jaekel } 747add9520fSAndreas Jaekel 748add9520fSAndreas Jaekel aq.zev_namelen = namelen; 749add9520fSAndreas Jaekel strcpy(aq.zev_name, arg); 7506a6a51eeSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 7516a6a51eeSAndreas Jaekel if (blocking) { 7526a6a51eeSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 7536a6a51eeSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 7546a6a51eeSAndreas Jaekel } else { 755add9520fSAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 7566a6a51eeSAndreas Jaekel } 757add9520fSAndreas Jaekel 758add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 759add9520fSAndreas Jaekel perror("adding queue failed"); 760a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 761a18c35b9SAndreas Jaekel } 762a18c35b9SAndreas Jaekel return (0); 763a18c35b9SAndreas Jaekel } 764a18c35b9SAndreas Jaekel 765a18c35b9SAndreas Jaekel static int 766add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg) 767fec460f8SAndreas Jaekel { 768add9520fSAndreas Jaekel zev_ioctl_remove_queue_t aq; 769add9520fSAndreas Jaekel int namelen; 770fec460f8SAndreas Jaekel 771add9520fSAndreas Jaekel namelen = strlen(arg); 772add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 773add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 774fec460f8SAndreas Jaekel return (EXIT_FAILURE); 775fec460f8SAndreas Jaekel } 776add9520fSAndreas Jaekel 7776a6a51eeSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 7786a6a51eeSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 779add9520fSAndreas Jaekel 780add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 781add9520fSAndreas Jaekel perror("removing queue failed"); 782add9520fSAndreas Jaekel return (EXIT_FAILURE); 783add9520fSAndreas Jaekel } 784add9520fSAndreas Jaekel return (0); 785add9520fSAndreas Jaekel } 786add9520fSAndreas Jaekel 787add9520fSAndreas Jaekel static int 788add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 789add9520fSAndreas Jaekel { 790add9520fSAndreas Jaekel uint64_t maxqueuelen; 791add9520fSAndreas Jaekel 792add9520fSAndreas Jaekel errno = 0; 793add9520fSAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 794add9520fSAndreas Jaekel if (errno) { 795add9520fSAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 796add9520fSAndreas Jaekel return (EXIT_FAILURE); 797add9520fSAndreas Jaekel } 798add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 799add9520fSAndreas Jaekel perror("setting max queue length failed"); 800fec460f8SAndreas Jaekel return (EXIT_FAILURE); 801fec460f8SAndreas Jaekel } 802fec460f8SAndreas Jaekel return (0); 803fec460f8SAndreas Jaekel } 804fec460f8SAndreas Jaekel 805fec460f8SAndreas Jaekel static int 806a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 807a18c35b9SAndreas Jaekel { 808a18c35b9SAndreas Jaekel zev_ioctl_poolarg_t pa; 809a18c35b9SAndreas Jaekel int len; 810a18c35b9SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 811a18c35b9SAndreas Jaekel len = strlen(poolname); 812a18c35b9SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 813a18c35b9SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 814a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 815a18c35b9SAndreas Jaekel } 816a18c35b9SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 817a18c35b9SAndreas Jaekel pa.zev_poolname_len = len; 818a18c35b9SAndreas Jaekel if (ioctl(fd, op, &pa)) { 819a18c35b9SAndreas Jaekel perror("muting pool data failed"); 820a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 821a18c35b9SAndreas Jaekel } 822a18c35b9SAndreas Jaekel return (0); 823a18c35b9SAndreas Jaekel } 824a18c35b9SAndreas Jaekel 825a18c35b9SAndreas Jaekel int 826a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 827a18c35b9SAndreas Jaekel { 828a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 829a18c35b9SAndreas Jaekel } 830a18c35b9SAndreas Jaekel 831a18c35b9SAndreas Jaekel int 832a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 833a18c35b9SAndreas Jaekel { 834a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 835a18c35b9SAndreas Jaekel } 836a18c35b9SAndreas Jaekel 837888fea18SAndreas Jaekel static int 838add9520fSAndreas Jaekel zev_debug_info(int fd) 839add9520fSAndreas Jaekel { 840add9520fSAndreas Jaekel zev_ioctl_debug_info_t di; 841add9520fSAndreas Jaekel 842add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 843add9520fSAndreas Jaekel perror("getting zev debug info failed"); 844add9520fSAndreas Jaekel return (EXIT_FAILURE); 845add9520fSAndreas Jaekel } 846add9520fSAndreas Jaekel 847add9520fSAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 848205ed6bfSAndreas Jaekel printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 849205ed6bfSAndreas Jaekel printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 850205ed6bfSAndreas Jaekel printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 851add9520fSAndreas Jaekel return 0; 852add9520fSAndreas Jaekel } 853add9520fSAndreas Jaekel 854add9520fSAndreas Jaekel static int 855888fea18SAndreas Jaekel zev_mark(int fd, char *arg) 856888fea18SAndreas Jaekel { 857888fea18SAndreas Jaekel zev_ioctl_mark_t *mark; 858888fea18SAndreas Jaekel uint64_t guid; 859888fea18SAndreas Jaekel int len; 860888fea18SAndreas Jaekel char *p; 861888fea18SAndreas Jaekel 862888fea18SAndreas Jaekel p = strchr(arg, ':'); 863888fea18SAndreas Jaekel if (!p) { 864888fea18SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 865888fea18SAndreas Jaekel "e.g. '123:hello'\n"); 866888fea18SAndreas Jaekel exit (EXIT_FAILURE); 867888fea18SAndreas Jaekel } 868888fea18SAndreas Jaekel *p = '\n'; 869888fea18SAndreas Jaekel p++; 870888fea18SAndreas Jaekel 871888fea18SAndreas Jaekel errno = 0; 872add9520fSAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 873888fea18SAndreas Jaekel if (errno) { 874888fea18SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 875888fea18SAndreas Jaekel exit (EXIT_FAILURE); 876888fea18SAndreas Jaekel } 877888fea18SAndreas Jaekel 878888fea18SAndreas Jaekel len = strlen(p); 879888fea18SAndreas Jaekel 880888fea18SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 881888fea18SAndreas Jaekel if (!mark) { 882888fea18SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 883888fea18SAndreas Jaekel strerror(errno)); 884888fea18SAndreas Jaekel exit (EXIT_FAILURE); 885888fea18SAndreas Jaekel } 886888fea18SAndreas Jaekel mark->zev_guid = guid; 887888fea18SAndreas Jaekel mark->zev_mark_id = 0; 888888fea18SAndreas Jaekel mark->zev_payload_len = len; 889888fea18SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 890888fea18SAndreas Jaekel 891888fea18SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 892888fea18SAndreas Jaekel perror("queueing mark failed"); 893888fea18SAndreas Jaekel return (EXIT_FAILURE); 894888fea18SAndreas Jaekel } 895888fea18SAndreas Jaekel 896888fea18SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 897888fea18SAndreas Jaekel return (0); 898888fea18SAndreas Jaekel } 899888fea18SAndreas Jaekel 900add9520fSAndreas Jaekel static int 901add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 902add9520fSAndreas Jaekel { 903add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 904add9520fSAndreas Jaekel 9056a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9066a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 907add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 908add9520fSAndreas Jaekel return EXIT_FAILURE; 909add9520fSAndreas Jaekel } 9106a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 911add9520fSAndreas Jaekel 912add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 913add9520fSAndreas Jaekel perror("getting queue properties failed"); 914add9520fSAndreas Jaekel return (EXIT_FAILURE); 915add9520fSAndreas Jaekel } 916add9520fSAndreas Jaekel if (block) { 917add9520fSAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 918add9520fSAndreas Jaekel } else { 919add9520fSAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 920add9520fSAndreas Jaekel } 921add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 922add9520fSAndreas Jaekel perror("setting queue properties failed"); 923add9520fSAndreas Jaekel return (EXIT_FAILURE); 924add9520fSAndreas Jaekel } 925add9520fSAndreas Jaekel return (0); 926add9520fSAndreas Jaekel } 927add9520fSAndreas Jaekel 928add9520fSAndreas Jaekel static int 929add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 930add9520fSAndreas Jaekel { 931add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 932add9520fSAndreas Jaekel 933add9520fSAndreas Jaekel if (!len) { 934add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 935add9520fSAndreas Jaekel return EXIT_FAILURE; 936add9520fSAndreas Jaekel } 937add9520fSAndreas Jaekel 9386a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9396a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 940add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 941add9520fSAndreas Jaekel return EXIT_FAILURE; 942add9520fSAndreas Jaekel } 9436a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 944add9520fSAndreas Jaekel 945add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 946add9520fSAndreas Jaekel perror("getting queue properties failed"); 947add9520fSAndreas Jaekel return (EXIT_FAILURE); 948add9520fSAndreas Jaekel } 949add9520fSAndreas Jaekel gqp.zev_max_queue_len = atol(len); 950add9520fSAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 951add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 952add9520fSAndreas Jaekel return (EXIT_FAILURE); 953add9520fSAndreas Jaekel } 954add9520fSAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 955add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 956add9520fSAndreas Jaekel return (EXIT_FAILURE); 957add9520fSAndreas Jaekel } 958add9520fSAndreas Jaekel 959add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 960add9520fSAndreas Jaekel perror("setting queue properties failed"); 961add9520fSAndreas Jaekel return (EXIT_FAILURE); 962add9520fSAndreas Jaekel } 963add9520fSAndreas Jaekel return (0); 964add9520fSAndreas Jaekel } 965add9520fSAndreas Jaekel 966add9520fSAndreas Jaekel static int 967add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 968add9520fSAndreas Jaekel { 969add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 970add9520fSAndreas Jaekel 971add9520fSAndreas Jaekel if (!len) { 972add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 973add9520fSAndreas Jaekel return EXIT_FAILURE; 974add9520fSAndreas Jaekel } 975add9520fSAndreas Jaekel 9766a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9776a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 978add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 979add9520fSAndreas Jaekel return EXIT_FAILURE; 980add9520fSAndreas Jaekel } 9816a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 982add9520fSAndreas Jaekel 983add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 984add9520fSAndreas Jaekel perror("getting queue properties failed"); 985add9520fSAndreas Jaekel return (EXIT_FAILURE); 986add9520fSAndreas Jaekel } 987add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 988add9520fSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 989add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 990add9520fSAndreas Jaekel return (EXIT_FAILURE); 991add9520fSAndreas Jaekel } 9926a6a51eeSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 993add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 994add9520fSAndreas Jaekel return (EXIT_FAILURE); 995add9520fSAndreas Jaekel } 996add9520fSAndreas Jaekel 997add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 998add9520fSAndreas Jaekel perror("setting queue properties failed"); 999add9520fSAndreas Jaekel return (EXIT_FAILURE); 1000add9520fSAndreas Jaekel } 1001add9520fSAndreas Jaekel return (0); 1002add9520fSAndreas Jaekel } 1003add9520fSAndreas Jaekel 1004add9520fSAndreas Jaekel static int 1005add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg) 1006add9520fSAndreas Jaekel { 1007add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1008add9520fSAndreas Jaekel 10096a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 10106a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 1011add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 1012add9520fSAndreas Jaekel return EXIT_FAILURE; 1013add9520fSAndreas Jaekel } 10146a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 1015add9520fSAndreas Jaekel 1016add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1017add9520fSAndreas Jaekel perror("getting queue properties failed"); 1018add9520fSAndreas Jaekel return (EXIT_FAILURE); 1019add9520fSAndreas Jaekel } 1020add9520fSAndreas Jaekel 1021add9520fSAndreas Jaekel printf("queue : %s\n", arg); 1022add9520fSAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1023add9520fSAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1024add9520fSAndreas Jaekel printf("persistent : %s\n", 1025add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1026add9520fSAndreas Jaekel printf("blocking : %s\n", 1027add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1028add9520fSAndreas Jaekel 1029add9520fSAndreas Jaekel return (0); 1030add9520fSAndreas Jaekel } 1031add9520fSAndreas Jaekel 1032add9520fSAndreas Jaekel static int 1033add9520fSAndreas Jaekel zev_list_queues(int fd) 1034add9520fSAndreas Jaekel { 1035add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1036add9520fSAndreas Jaekel zev_ioctl_get_queue_list_t gql; 1037add9520fSAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 1038add9520fSAndreas Jaekel uint64_t i; 1039add9520fSAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1040add9520fSAndreas Jaekel 1041add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1042add9520fSAndreas Jaekel perror("getting queue list failed"); 1043add9520fSAndreas Jaekel return (EXIT_FAILURE); 1044add9520fSAndreas Jaekel } 1045add9520fSAndreas Jaekel 1046add9520fSAndreas Jaekel printf("Name Size " 1047add9520fSAndreas Jaekel "Max Size Wakeup Per Block\n"); 1048add9520fSAndreas Jaekel 1049add9520fSAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 1050add9520fSAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 1051add9520fSAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 1052add9520fSAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1053add9520fSAndreas Jaekel 10546a6a51eeSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 10556a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10566a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 10576a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1058add9520fSAndreas Jaekel 1059add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1060add9520fSAndreas Jaekel if (errno == ENOENT) 1061add9520fSAndreas Jaekel continue; 1062add9520fSAndreas Jaekel perror("getting queue properties failed"); 1063add9520fSAndreas Jaekel return (EXIT_FAILURE); 1064add9520fSAndreas Jaekel } 1065add9520fSAndreas Jaekel 10666a6a51eeSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 10676a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10686a6a51eeSAndreas Jaekel gs.zev_queue_name.zev_namelen = 10696a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1070add9520fSAndreas Jaekel 1071add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1072add9520fSAndreas Jaekel if (errno == ENOENT) 1073add9520fSAndreas Jaekel continue; 1074add9520fSAndreas Jaekel perror("getting statistics data failed"); 1075add9520fSAndreas Jaekel return (EXIT_FAILURE); 1076add9520fSAndreas Jaekel } 1077add9520fSAndreas Jaekel 1078add9520fSAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1079add9520fSAndreas Jaekel " %-3s %-3s\n", 1080add9520fSAndreas Jaekel name, 1081add9520fSAndreas Jaekel gs.zev_statistics.zev_queue_len, 1082add9520fSAndreas Jaekel gqp.zev_max_queue_len, 1083add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold, 1084add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1085add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1086add9520fSAndreas Jaekel "yes" : "no"); 1087add9520fSAndreas Jaekel } 1088add9520fSAndreas Jaekel 1089add9520fSAndreas Jaekel return (0); 1090add9520fSAndreas Jaekel } 1091add9520fSAndreas Jaekel 109242110aacSAndreas Jaekel static int 109342110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename) 109442110aacSAndreas Jaekel { 109542110aacSAndreas Jaekel int fd; 109642110aacSAndreas Jaekel offset_t off; 109742110aacSAndreas Jaekel offset_t data; 109842110aacSAndreas Jaekel zev_sig_t *sig; 109942110aacSAndreas Jaekel char *buf; 110042110aacSAndreas Jaekel zev_ioctl_get_signatures_t *gs; 110142110aacSAndreas Jaekel int i; 110242110aacSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 110342110aacSAndreas Jaekel int buf_size; 110442110aacSAndreas Jaekel 110542110aacSAndreas Jaekel /* control struct, one lv1 signature and up to 256 lv0 signatures */ 110642110aacSAndreas Jaekel buf_size = (1 + 256) * sizeof(zev_sig_t); 110742110aacSAndreas Jaekel buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 110842110aacSAndreas Jaekel if (!buf) { 110942110aacSAndreas Jaekel perror("can't allocate checksum buffer"); 111042110aacSAndreas Jaekel return (EXIT_FAILURE); 111142110aacSAndreas Jaekel } 111242110aacSAndreas Jaekel 111342110aacSAndreas Jaekel fd = open(filename, O_RDONLY); 111442110aacSAndreas Jaekel if (fd < 0) { 111542110aacSAndreas Jaekel perror("can't open file"); 111642110aacSAndreas Jaekel return (EXIT_FAILURE); 111742110aacSAndreas Jaekel } 111842110aacSAndreas Jaekel 111942110aacSAndreas Jaekel gs = (zev_ioctl_get_signatures_t *)buf; 112042110aacSAndreas Jaekel gs->zev_fd = fd; 112142110aacSAndreas Jaekel gs->zev_bufsize = buf_size; 112242110aacSAndreas Jaekel 112342110aacSAndreas Jaekel off = 0; 112442110aacSAndreas Jaekel data = 0; 112542110aacSAndreas Jaekel while (1) { 112642110aacSAndreas Jaekel errno = 0; 112742110aacSAndreas Jaekel data = llseek(fd, off, SEEK_DATA); 112842110aacSAndreas Jaekel if (data < 0) { 112942110aacSAndreas Jaekel if (errno == ENXIO) /* no more data */ 113042110aacSAndreas Jaekel break; 113142110aacSAndreas Jaekel perror("llseek failed"); 113242110aacSAndreas Jaekel goto err; 113342110aacSAndreas Jaekel } 113442110aacSAndreas Jaekel data = P2ALIGN(data, ZEV_L1_SIZE); 113542110aacSAndreas Jaekel off = data + ZEV_L1_SIZE; 113642110aacSAndreas Jaekel 113742110aacSAndreas Jaekel gs->zev_offset = data; 113842110aacSAndreas Jaekel gs->zev_len = ZEV_L1_SIZE; 113942110aacSAndreas Jaekel 114042110aacSAndreas Jaekel if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 114142110aacSAndreas Jaekel perror("ioctl to get signatures failed"); 114242110aacSAndreas Jaekel goto err; 114342110aacSAndreas Jaekel } 114442110aacSAndreas Jaekel 114542110aacSAndreas Jaekel for (i=0; i<gs->zev_signature_cnt; i++) { 114642110aacSAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 114742110aacSAndreas Jaekel sig += i; 114842110aacSAndreas Jaekel sig2hex_direct(sig->value, sigval); 114942110aacSAndreas Jaekel printf("level %d, offset %llu, value %s\n", 115042110aacSAndreas Jaekel sig->level, sig->block_offset, sigval); 115142110aacSAndreas Jaekel } 115242110aacSAndreas Jaekel } 115342110aacSAndreas Jaekel 115442110aacSAndreas Jaekel free(buf); 115542110aacSAndreas Jaekel close(fd); 115642110aacSAndreas Jaekel return 0; 115742110aacSAndreas Jaekel err: 115842110aacSAndreas Jaekel free(buf); 115942110aacSAndreas Jaekel close(fd); 116042110aacSAndreas Jaekel return (EXIT_FAILURE); 116142110aacSAndreas Jaekel } 116242110aacSAndreas Jaekel 1163a18c35b9SAndreas Jaekel int 1164a18c35b9SAndreas Jaekel main(int argc, char **argv) 1165a18c35b9SAndreas Jaekel { 1166a18c35b9SAndreas Jaekel int fd; 1167a18c35b9SAndreas Jaekel int c; 1168a18c35b9SAndreas Jaekel extern char *optarg; 11696a6a51eeSAndreas Jaekel int create_tmp_queue = 1; 11706a6a51eeSAndreas Jaekel char buf[MAXPATHLEN]; 1171a18c35b9SAndreas Jaekel 1172a18c35b9SAndreas Jaekel /* open device */ 1173a18c35b9SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1174a18c35b9SAndreas Jaekel if (fd < 0) { 1175a18c35b9SAndreas Jaekel perror("opening zev device failed"); 1176a18c35b9SAndreas Jaekel return EXIT_FAILURE; 1177a18c35b9SAndreas Jaekel } 11786a6a51eeSAndreas Jaekel while ((c = getopt(argc, argv, 117916ff6b2fSAndreas Jaekel "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 1180a18c35b9SAndreas Jaekel switch(c) { 118116ff6b2fSAndreas Jaekel case 'g': 118216ff6b2fSAndreas Jaekel grep_friendly++; 118316ff6b2fSAndreas Jaekel verbose++; 118416ff6b2fSAndreas Jaekel break; 1185205ed6bfSAndreas Jaekel case 'v': 1186205ed6bfSAndreas Jaekel verbose++; 1187205ed6bfSAndreas Jaekel break; 1188a18c35b9SAndreas Jaekel case 's': 1189add9520fSAndreas Jaekel return zev_statistics(fd); 1190a18c35b9SAndreas Jaekel case 'p': 11916a6a51eeSAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 119242110aacSAndreas Jaekel case 'c': 119342110aacSAndreas Jaekel return zev_checksum(fd, optarg); 1194add9520fSAndreas Jaekel case 'D': 1195add9520fSAndreas Jaekel return zev_debug_info(fd); 1196a18c35b9SAndreas Jaekel case 'd': 1197add9520fSAndreas Jaekel close(fd); 1198a18c35b9SAndreas Jaekel zev_device = optarg; 1199add9520fSAndreas Jaekel fd = open(zev_device, O_RDONLY); 1200add9520fSAndreas Jaekel if (fd < 0) { 1201add9520fSAndreas Jaekel perror("opening zev device failed"); 1202add9520fSAndreas Jaekel return EXIT_FAILURE; 1203add9520fSAndreas Jaekel } 12046a6a51eeSAndreas Jaekel create_tmp_queue = 0; 12056a6a51eeSAndreas Jaekel break; 12066a6a51eeSAndreas Jaekel case 'q': 12076a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 12086a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 12096a6a51eeSAndreas Jaekel close(fd); 12106a6a51eeSAndreas Jaekel zev_device = buf; 12116a6a51eeSAndreas Jaekel fd = open(zev_device, O_RDONLY); 12126a6a51eeSAndreas Jaekel if (fd < 0) { 12136a6a51eeSAndreas Jaekel perror("opening zev device failed"); 12146a6a51eeSAndreas Jaekel return EXIT_FAILURE; 12156a6a51eeSAndreas Jaekel } 12166a6a51eeSAndreas Jaekel create_tmp_queue = 0; 1217a18c35b9SAndreas Jaekel break; 1218add9520fSAndreas Jaekel case 'l': 1219add9520fSAndreas Jaekel return zev_list_queues(fd); 1220add9520fSAndreas Jaekel case 'Q': 1221add9520fSAndreas Jaekel return zev_set_global_max_queue_len(fd, optarg); 12226a6a51eeSAndreas Jaekel case 'L': 1223add9520fSAndreas Jaekel return zev_set_max_queue_len(fd, optarg, argv[optind]); 1224fec460f8SAndreas Jaekel case 't': 1225add9520fSAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg, 1226add9520fSAndreas Jaekel argv[optind]); 1227a18c35b9SAndreas Jaekel case 'm': 1228a18c35b9SAndreas Jaekel return zev_mute_pool(fd, optarg); 1229a18c35b9SAndreas Jaekel case 'M': 1230a18c35b9SAndreas Jaekel return zev_unmute_pool(fd, optarg); 1231888fea18SAndreas Jaekel case 'k': 1232888fea18SAndreas Jaekel return zev_mark(fd, optarg); 1233add9520fSAndreas Jaekel case 'a': 12346a6a51eeSAndreas Jaekel return zev_add_queue(fd, optarg, 0); 12356a6a51eeSAndreas Jaekel case 'A': 12366a6a51eeSAndreas Jaekel return zev_add_queue(fd, optarg, 1); 1237add9520fSAndreas Jaekel case 'r': 1238add9520fSAndreas Jaekel return zev_remove_queue(fd, optarg); 1239add9520fSAndreas Jaekel case 'b': 1240add9520fSAndreas Jaekel return zev_queue_blocking(fd, optarg, 0); 1241add9520fSAndreas Jaekel case 'B': 1242add9520fSAndreas Jaekel return zev_queue_blocking(fd, optarg, 1); 1243add9520fSAndreas Jaekel case 'P': 1244add9520fSAndreas Jaekel return zev_queue_properties(fd, optarg); 1245a18c35b9SAndreas Jaekel case 'h': 1246a18c35b9SAndreas Jaekel case '?': 1247a18c35b9SAndreas Jaekel default: 1248a18c35b9SAndreas Jaekel usage(argv[0]); 1249a18c35b9SAndreas Jaekel } 1250a18c35b9SAndreas Jaekel } 1251a18c35b9SAndreas Jaekel usage(argv[0]); 1252a18c35b9SAndreas Jaekel close(fd); 1253add9520fSAndreas Jaekel return EXIT_FAILURE; 1254a18c35b9SAndreas Jaekel } 1255a18c35b9SAndreas Jaekel 1256