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> 11*16ff6b2fSAndreas 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[] = { 18*16ff6b2fSAndreas Jaekel "ERROR", 19*16ff6b2fSAndreas Jaekel "MARK", 20*16ff6b2fSAndreas Jaekel "ZFS_MOUNT", 21*16ff6b2fSAndreas Jaekel "ZFS_UMOUNT", 22*16ff6b2fSAndreas Jaekel "ZVOL_WRITE", 23*16ff6b2fSAndreas Jaekel "ZVOL_TRUNCATE", 24*16ff6b2fSAndreas Jaekel "ZNODE_CLOSE_AFTER_UPDATE", 25*16ff6b2fSAndreas Jaekel "ZNODE_CREATE", 26*16ff6b2fSAndreas Jaekel "ZNODE_MKDIR", 27*16ff6b2fSAndreas Jaekel "ZNODE_MAKE_XATTR_DIR", 28*16ff6b2fSAndreas Jaekel "ZNODE_REMOVE", 29*16ff6b2fSAndreas Jaekel "ZNODE_RMDIR", 30*16ff6b2fSAndreas Jaekel "ZNODE_LINK", 31*16ff6b2fSAndreas Jaekel "ZNODE_SYMLINK", 32*16ff6b2fSAndreas Jaekel "ZNODE_RENAME", 33*16ff6b2fSAndreas Jaekel "ZNODE_WRITE", 34*16ff6b2fSAndreas Jaekel "ZNODE_TRUNCATE", 35*16ff6b2fSAndreas Jaekel "ZNODE_SETATTR", 36*16ff6b2fSAndreas Jaekel "ZNODE_ACL", 37aafc540fSAndreas Jaekel NULL 38aafc540fSAndreas Jaekel }; 39aafc540fSAndreas Jaekel 40205ed6bfSAndreas Jaekel static int verbose = 0; 41*16ff6b2fSAndreas Jaekel static int grep_friendly = 0; 42*16ff6b2fSAndreas Jaekel 43*16ff6b2fSAndreas Jaekel static void 44*16ff6b2fSAndreas Jaekel zpf(char *fmt, ...) 45*16ff6b2fSAndreas Jaekel { 46*16ff6b2fSAndreas Jaekel va_list ap; 47*16ff6b2fSAndreas Jaekel 48*16ff6b2fSAndreas Jaekel va_start(ap, fmt); 49*16ff6b2fSAndreas Jaekel vprintf(fmt, ap); 50*16ff6b2fSAndreas Jaekel va_end(ap); 51*16ff6b2fSAndreas Jaekel if (grep_friendly) { 52*16ff6b2fSAndreas Jaekel printf(" "); 53*16ff6b2fSAndreas Jaekel } else { 54*16ff6b2fSAndreas Jaekel printf("\n"); 55*16ff6b2fSAndreas Jaekel } 56*16ff6b2fSAndreas Jaekel } 57*16ff6b2fSAndreas Jaekel 58*16ff6b2fSAndreas Jaekel static void 59*16ff6b2fSAndreas Jaekel znl(void) 60*16ff6b2fSAndreas Jaekel { 61*16ff6b2fSAndreas Jaekel if (grep_friendly) 62*16ff6b2fSAndreas Jaekel printf("\n"); 63*16ff6b2fSAndreas Jaekel } 64205ed6bfSAndreas Jaekel 65add9520fSAndreas Jaekel static int 66a18c35b9SAndreas Jaekel zev_statistics(int fd) 67a18c35b9SAndreas Jaekel { 68a18c35b9SAndreas Jaekel zev_statistics_t zs; 69add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 70a18c35b9SAndreas Jaekel perror("getting statistics data failed"); 71add9520fSAndreas Jaekel return (EXIT_FAILURE); 72a18c35b9SAndreas Jaekel } 73a18c35b9SAndreas Jaekel printf("ZEV module state:\n"); 74a18c35b9SAndreas Jaekel 75a18c35b9SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 76a18c35b9SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 77a18c35b9SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 78a18c35b9SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 79a18c35b9SAndreas Jaekel 80add9520fSAndreas Jaekel printf(" discarded events : %lu\n", 81add9520fSAndreas Jaekel zs.zev_cnt_discarded_events); 82add9520fSAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 83add9520fSAndreas Jaekel 84a18c35b9SAndreas Jaekel printf("ZFS event statistics:\n"); 85a18c35b9SAndreas Jaekel 86a18c35b9SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 87a18c35b9SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 88a18c35b9SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 89a18c35b9SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 90a18c35b9SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 91a18c35b9SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 92a18c35b9SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 93a18c35b9SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 94a18c35b9SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 95a18c35b9SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 96a18c35b9SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 97a18c35b9SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 98a18c35b9SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 99a18c35b9SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 100a18c35b9SAndreas Jaekel zs.zev_cnt_znode_truncate); 101a18c35b9SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 102a18c35b9SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 103add9520fSAndreas Jaekel return EXIT_SUCCESS; 104a18c35b9SAndreas Jaekel } 105a18c35b9SAndreas Jaekel 106a18c35b9SAndreas Jaekel static void 107*16ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info) 108*16ff6b2fSAndreas Jaekel { 109*16ff6b2fSAndreas Jaekel zpf(" %s.inode: %llu", name, info->ino); 110*16ff6b2fSAndreas Jaekel zpf(" %s.gen: %llu", name, info->gen); 111*16ff6b2fSAndreas Jaekel zpf(" %s.mtime: %llu", name, info->mtime); 112*16ff6b2fSAndreas Jaekel zpf(" %s.ctime: %llu", name, info->ctime); 113*16ff6b2fSAndreas Jaekel zpf(" %s.size: %llu", name, info->size); 114*16ff6b2fSAndreas Jaekel zpf(" %s.mode: %llo", name, info->mode); 115*16ff6b2fSAndreas Jaekel zpf(" %s.links: %llu", name, info->links); 116*16ff6b2fSAndreas Jaekel zpf(" %s.type: %lu", name, info->type); 117*16ff6b2fSAndreas Jaekel zpf(" %s.flags: %lu", name, info->flags); 118*16ff6b2fSAndreas Jaekel } 119*16ff6b2fSAndreas Jaekel 120*16ff6b2fSAndreas Jaekel static void 121*16ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec) 122*16ff6b2fSAndreas Jaekel { 123*16ff6b2fSAndreas Jaekel int i; 124*16ff6b2fSAndreas Jaekel int j; 125*16ff6b2fSAndreas Jaekel uint8_t *p; 126*16ff6b2fSAndreas Jaekel char c; 127*16ff6b2fSAndreas Jaekel 128*16ff6b2fSAndreas Jaekel zpf(" payload:"); 129*16ff6b2fSAndreas Jaekel p = (uint8_t *)ZEV_PAYLOAD(rec); 130*16ff6b2fSAndreas Jaekel for (i=0; i<rec->payload_len; i+=16) { 131*16ff6b2fSAndreas Jaekel printf(" "); 132*16ff6b2fSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 133*16ff6b2fSAndreas Jaekel printf("%02x ", p[j]); 134*16ff6b2fSAndreas Jaekel if (j == i + 7) 135*16ff6b2fSAndreas Jaekel printf(" "); 136*16ff6b2fSAndreas Jaekel } 137*16ff6b2fSAndreas Jaekel if (grep_friendly) 138*16ff6b2fSAndreas Jaekel continue; 139*16ff6b2fSAndreas Jaekel for (; j<i+16; j++) { 140*16ff6b2fSAndreas Jaekel printf(" "); 141*16ff6b2fSAndreas Jaekel if (j == i + 7) 142*16ff6b2fSAndreas Jaekel printf(" "); 143*16ff6b2fSAndreas Jaekel } 144*16ff6b2fSAndreas Jaekel printf(" "); 145*16ff6b2fSAndreas Jaekel for (j=i; j<rec->payload_len && j<i+16; j++) { 146*16ff6b2fSAndreas Jaekel c = '.'; 147*16ff6b2fSAndreas Jaekel if (p[j] >= ' ' && p[j] <= '~') 148*16ff6b2fSAndreas Jaekel c = p[j]; 149*16ff6b2fSAndreas Jaekel printf("%c", c); 150*16ff6b2fSAndreas Jaekel if (j == i + 7) 151*16ff6b2fSAndreas Jaekel printf(" "); 152*16ff6b2fSAndreas Jaekel } 153*16ff6b2fSAndreas Jaekel printf("\n"); 154*16ff6b2fSAndreas Jaekel } 155*16ff6b2fSAndreas Jaekel } 156*16ff6b2fSAndreas Jaekel 157*16ff6b2fSAndreas Jaekel static void 158f2dd45e5SAndreas Jaekel zev_print_error(char *buf) 159f2dd45e5SAndreas Jaekel { 160f2dd45e5SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 161f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 162f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 163f2dd45e5SAndreas Jaekel 164*16ff6b2fSAndreas Jaekel if (verbose) { 165*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 166*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 167*16ff6b2fSAndreas Jaekel zpf(" failed.op: %s", 168*16ff6b2fSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN]); 169*16ff6b2fSAndreas Jaekel zpf(" message: %s", ZEV_ERRSTR(rec)); 170*16ff6b2fSAndreas Jaekel znl(); 171*16ff6b2fSAndreas Jaekel } else { 172f2dd45e5SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 173f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 174*16ff6b2fSAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], 175*16ff6b2fSAndreas Jaekel ZEV_ERRSTR(rec)); 176*16ff6b2fSAndreas Jaekel } 177f2dd45e5SAndreas Jaekel } 178f2dd45e5SAndreas Jaekel 179f2dd45e5SAndreas Jaekel static void 180888fea18SAndreas Jaekel zev_print_mark(char *buf) 181888fea18SAndreas Jaekel { 182888fea18SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 183888fea18SAndreas Jaekel time_t op_time = rec->op_time; 184888fea18SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 185888fea18SAndreas Jaekel 186*16ff6b2fSAndreas Jaekel if (verbose) { 187*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 188*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 189*16ff6b2fSAndreas Jaekel zpf(" mark.id: %llu", rec->mark_id); 190*16ff6b2fSAndreas Jaekel zpf(" payload.len: %llu", rec->payload_len); 191*16ff6b2fSAndreas Jaekel if (rec->payload_len) 192*16ff6b2fSAndreas Jaekel zev_print_mark_payload(rec); 193*16ff6b2fSAndreas Jaekel znl(); 194*16ff6b2fSAndreas Jaekel } else { 195888fea18SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 196*16ff6b2fSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, 197*16ff6b2fSAndreas Jaekel rec->mark_id, rec->payload_len); 198*16ff6b2fSAndreas Jaekel } 199888fea18SAndreas Jaekel } 200888fea18SAndreas Jaekel 201888fea18SAndreas Jaekel static void 202f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf) 203f2dd45e5SAndreas Jaekel { 204f2dd45e5SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 205f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 206f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 207f2dd45e5SAndreas Jaekel 208*16ff6b2fSAndreas Jaekel if (verbose) { 209*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 210*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 211*16ff6b2fSAndreas Jaekel zpf(" dataset: %s", ZEV_DATASET(rec)); 212*16ff6b2fSAndreas Jaekel zpf(" mountpoint: %s", ZEV_MOUNTPOINT(rec)); 213*16ff6b2fSAndreas Jaekel zpf(" remount: %s", rec->remount ? "true" : "false"); 214*16ff6b2fSAndreas Jaekel zev_print_inode_info("root", &rec->root); 215*16ff6b2fSAndreas Jaekel znl(); 216*16ff6b2fSAndreas Jaekel } else { 217*16ff6b2fSAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' " 218*16ff6b2fSAndreas Jaekel "mountpoint='%s'\n", 219f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 220f2dd45e5SAndreas Jaekel rec->guid, 221f2dd45e5SAndreas Jaekel rec->remount ? "true" : "false", 222f2dd45e5SAndreas Jaekel ZEV_DATASET(rec), 223f2dd45e5SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 224f2dd45e5SAndreas Jaekel } 225*16ff6b2fSAndreas Jaekel } 226f2dd45e5SAndreas Jaekel 227f2dd45e5SAndreas Jaekel static void 228f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf) 229f2dd45e5SAndreas Jaekel { 230f2dd45e5SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 231f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 232f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 233f2dd45e5SAndreas Jaekel 234*16ff6b2fSAndreas Jaekel if (verbose) { 235*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 236*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 237*16ff6b2fSAndreas Jaekel znl(); 238*16ff6b2fSAndreas Jaekel } else { 239f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu\n", 240f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 241f2dd45e5SAndreas Jaekel rec->guid); 242f2dd45e5SAndreas Jaekel } 243*16ff6b2fSAndreas Jaekel } 244f2dd45e5SAndreas Jaekel 245f2dd45e5SAndreas Jaekel static void 246f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf) 247f2dd45e5SAndreas Jaekel { 248f2dd45e5SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 249f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 250f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 251f2dd45e5SAndreas Jaekel 252*16ff6b2fSAndreas Jaekel if (verbose) { 253*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 254*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 255*16ff6b2fSAndreas Jaekel zpf(" offset: %llu", rec->offset); 256*16ff6b2fSAndreas Jaekel zpf(" length: %llu", rec->length); 257*16ff6b2fSAndreas Jaekel znl(); 258*16ff6b2fSAndreas Jaekel } else { 259f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 260f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 261f2dd45e5SAndreas Jaekel rec->guid, 262f2dd45e5SAndreas Jaekel rec->offset, 263f2dd45e5SAndreas Jaekel rec->length); 264f2dd45e5SAndreas Jaekel } 265*16ff6b2fSAndreas Jaekel } 266f2dd45e5SAndreas Jaekel 267f2dd45e5SAndreas Jaekel static void 268f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf) 269f2dd45e5SAndreas Jaekel { 270f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 271f2dd45e5SAndreas Jaekel } 272f2dd45e5SAndreas Jaekel 273f2dd45e5SAndreas Jaekel static void 274f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 275f2dd45e5SAndreas Jaekel { 276f2dd45e5SAndreas Jaekel zev_znode_close_after_update_t *rec = 277f2dd45e5SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 278f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 279f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 280f2dd45e5SAndreas Jaekel 281*16ff6b2fSAndreas Jaekel if (verbose) { 282*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 283*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 284*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 285*16ff6b2fSAndreas Jaekel znl(); 286*16ff6b2fSAndreas Jaekel } else { 287f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 288f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 289f2dd45e5SAndreas Jaekel rec->guid, 290f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen); 291f2dd45e5SAndreas Jaekel } 292*16ff6b2fSAndreas Jaekel } 293f2dd45e5SAndreas Jaekel 294f2dd45e5SAndreas Jaekel static void 295f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf) 296f2dd45e5SAndreas Jaekel { 297f2dd45e5SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 298f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 299f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 300f2dd45e5SAndreas Jaekel 301*16ff6b2fSAndreas Jaekel if (verbose) { 302*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 303*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 304*16ff6b2fSAndreas Jaekel zpf(" name: '%s'", ZEV_NAME(rec)); 305*16ff6b2fSAndreas Jaekel zev_print_inode_info("parent", &rec->file); 306*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 307*16ff6b2fSAndreas Jaekel znl(); 308*16ff6b2fSAndreas Jaekel } else { 30935d4e8ddSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 31035d4e8ddSAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 311f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 312f2dd45e5SAndreas Jaekel rec->guid, 313f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 314f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 31535d4e8ddSAndreas Jaekel rec->file.mtime, rec->parent.mtime, 316f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 317f2dd45e5SAndreas Jaekel } 318*16ff6b2fSAndreas Jaekel } 319f2dd45e5SAndreas Jaekel 320f2dd45e5SAndreas Jaekel static void 321f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf) 322f2dd45e5SAndreas Jaekel { 323f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 324f2dd45e5SAndreas Jaekel } 325f2dd45e5SAndreas Jaekel 326f2dd45e5SAndreas Jaekel static void 327f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 328f2dd45e5SAndreas Jaekel { 329f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 330f2dd45e5SAndreas Jaekel } 331f2dd45e5SAndreas Jaekel 332f2dd45e5SAndreas Jaekel static void 333f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf) 334f2dd45e5SAndreas Jaekel { 335f2dd45e5SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 336f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 337f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 338f2dd45e5SAndreas Jaekel 339*16ff6b2fSAndreas Jaekel if (verbose) { 340*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 341*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 342*16ff6b2fSAndreas Jaekel zpf(" file.name: '%s'", ZEV_NAME(rec)); 343*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 344*16ff6b2fSAndreas Jaekel zev_print_inode_info("parent", &rec->file); 345*16ff6b2fSAndreas Jaekel znl(); 346*16ff6b2fSAndreas Jaekel } else { 347*16ff6b2fSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu " 348*16ff6b2fSAndreas Jaekel "file.mtime=%llu name='%s'\n", 349f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 350f2dd45e5SAndreas Jaekel rec->guid, 351f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 35297dcf88dSAndreas Jaekel rec->file.mtime, 353f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 354f2dd45e5SAndreas Jaekel } 355*16ff6b2fSAndreas Jaekel } 356f2dd45e5SAndreas Jaekel 357f2dd45e5SAndreas Jaekel static void 358f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf) 359f2dd45e5SAndreas Jaekel { 360f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 361f2dd45e5SAndreas Jaekel } 362f2dd45e5SAndreas Jaekel 363f2dd45e5SAndreas Jaekel static void 364f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf) 365f2dd45e5SAndreas Jaekel { 366f2dd45e5SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 367f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 368f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 369f2dd45e5SAndreas Jaekel 370*16ff6b2fSAndreas Jaekel if (verbose) { 371*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 372*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 373*16ff6b2fSAndreas Jaekel zpf(" link.name: '%s'", ZEV_NAME(rec)); 374*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 375*16ff6b2fSAndreas Jaekel zev_print_inode_info("parent", &rec->file); 376*16ff6b2fSAndreas Jaekel znl(); 377*16ff6b2fSAndreas Jaekel } else { 378a01b300aSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 379a01b300aSAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 380f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 381f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 382f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 383a01b300aSAndreas Jaekel rec->file.ctime, rec->parent.ctime, 384f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 385*16ff6b2fSAndreas Jaekel } 386f2dd45e5SAndreas Jaekel } 387f2dd45e5SAndreas Jaekel 388f2dd45e5SAndreas Jaekel static void 389f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf) 390f2dd45e5SAndreas Jaekel { 391f2dd45e5SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 392f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 393f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 394f2dd45e5SAndreas Jaekel 395*16ff6b2fSAndreas Jaekel if (verbose) { 396*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 397*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 398*16ff6b2fSAndreas Jaekel zpf(" symlink.name: '%s'", ZEV_NAME(rec)); 399*16ff6b2fSAndreas Jaekel zpf(" symlink.link: '%s'", ZEV_LINK(rec)); 400*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 401*16ff6b2fSAndreas Jaekel zev_print_inode_info("parent", &rec->file); 402*16ff6b2fSAndreas Jaekel znl(); 403*16ff6b2fSAndreas Jaekel } else { 404*16ff6b2fSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 405*16ff6b2fSAndreas Jaekel "name='%s' link='%s'\n", 406f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 407f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 408f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 409f2dd45e5SAndreas Jaekel ZEV_NAME(rec), 410f2dd45e5SAndreas Jaekel ZEV_LINK(rec)); 411f2dd45e5SAndreas Jaekel } 412*16ff6b2fSAndreas Jaekel } 413f2dd45e5SAndreas Jaekel 414f2dd45e5SAndreas Jaekel static void 415f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf) 416f2dd45e5SAndreas Jaekel { 417f2dd45e5SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 418f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 419f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 420f2dd45e5SAndreas Jaekel 421*16ff6b2fSAndreas Jaekel if (verbose) { 422*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 423*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 424*16ff6b2fSAndreas Jaekel zpf(" file.srcname: '%s'", ZEV_SRCNAME(rec)); 425*16ff6b2fSAndreas Jaekel zpf(" file.dstname: '%s'", ZEV_DSTNAME(rec)); 426*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 427*16ff6b2fSAndreas Jaekel zev_print_inode_info("srcdir", &rec->srcdir); 428*16ff6b2fSAndreas Jaekel zev_print_inode_info("dstdir", &rec->dstdir); 429*16ff6b2fSAndreas Jaekel znl(); 430*16ff6b2fSAndreas Jaekel } else { 431*16ff6b2fSAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu " 432*16ff6b2fSAndreas Jaekel "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, " 433*16ff6b2fSAndreas Jaekel "srcdir.mtime=%llu, srcdir.ctime=%llu, " 434*16ff6b2fSAndreas Jaekel "dstdir.mtime=%llu, dstdir.ctime=%llu, " 435f2dd45e5SAndreas Jaekel "srcname='%s' dstname='%s'\n", 436f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 437f2dd45e5SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 438f2dd45e5SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 439f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 44035d4e8ddSAndreas Jaekel rec->file.mtime, rec->file.ctime, 44135d4e8ddSAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 44235d4e8ddSAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 443f2dd45e5SAndreas Jaekel ZEV_SRCNAME(rec), 444f2dd45e5SAndreas Jaekel ZEV_DSTNAME(rec)); 445f2dd45e5SAndreas Jaekel } 446*16ff6b2fSAndreas Jaekel } 447f2dd45e5SAndreas Jaekel 448f2dd45e5SAndreas Jaekel static void 449205ed6bfSAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex) 450205ed6bfSAndreas Jaekel { 451205ed6bfSAndreas Jaekel int i; 452205ed6bfSAndreas Jaekel 453205ed6bfSAndreas Jaekel for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) { 454205ed6bfSAndreas Jaekel sprintf(hex + 2 * i, "%02x", sig[i]); 455205ed6bfSAndreas Jaekel } 456205ed6bfSAndreas Jaekel hex[SHA1_DIGEST_LENGTH * 2] = '\0'; 457205ed6bfSAndreas Jaekel } 458205ed6bfSAndreas Jaekel 459205ed6bfSAndreas Jaekel static void 460f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf) 461f2dd45e5SAndreas Jaekel { 462f2dd45e5SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 463f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 464f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 465205ed6bfSAndreas Jaekel zev_sig_t *sig; 466205ed6bfSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 467205ed6bfSAndreas Jaekel int i; 468f2dd45e5SAndreas Jaekel 469205ed6bfSAndreas Jaekel if (verbose) { 470*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 471*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 472*16ff6b2fSAndreas Jaekel zpf(" offset: %llu", rec->offset); 473*16ff6b2fSAndreas Jaekel zpf(" length: %llu", rec->length); 474*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 475*16ff6b2fSAndreas Jaekel znl(); 476205ed6bfSAndreas Jaekel for (i=0; i<rec->signature_cnt; i++) { 477205ed6bfSAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(rec); 478205ed6bfSAndreas Jaekel sig += i; 479205ed6bfSAndreas Jaekel sig2hex_direct(sig->value, sigval); 480205ed6bfSAndreas Jaekel printf(" sig: level %d, offset %llu, value %s\n", 481205ed6bfSAndreas Jaekel sig->level, sig->block_offset, sigval); 482205ed6bfSAndreas Jaekel } 483*16ff6b2fSAndreas Jaekel } else { 484*16ff6b2fSAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 485*16ff6b2fSAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 486*16ff6b2fSAndreas Jaekel rec->file.ino, rec->file.gen, 487*16ff6b2fSAndreas Jaekel rec->offset, rec->length); 488205ed6bfSAndreas Jaekel } 489f2dd45e5SAndreas Jaekel } 490f2dd45e5SAndreas Jaekel 491f2dd45e5SAndreas Jaekel static void 492f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf) 493f2dd45e5SAndreas Jaekel { 494f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 495f2dd45e5SAndreas Jaekel } 496f2dd45e5SAndreas Jaekel 497f2dd45e5SAndreas Jaekel static void 498f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf) 499f2dd45e5SAndreas Jaekel { 500f2dd45e5SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 501f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 502f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 503f2dd45e5SAndreas Jaekel 504*16ff6b2fSAndreas Jaekel if (verbose) { 505*16ff6b2fSAndreas Jaekel zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]); 506*16ff6b2fSAndreas Jaekel zpf(" guid: %llu", rec->guid); 507*16ff6b2fSAndreas Jaekel zev_print_inode_info("file", &rec->file); 508*16ff6b2fSAndreas Jaekel znl(); 509*16ff6b2fSAndreas Jaekel } else { 51035d4e8ddSAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 511f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 51235d4e8ddSAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 513f2dd45e5SAndreas Jaekel } 514*16ff6b2fSAndreas Jaekel } 515f2dd45e5SAndreas Jaekel 516f2dd45e5SAndreas Jaekel static void 517f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf) 518f2dd45e5SAndreas Jaekel { 519f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 520f2dd45e5SAndreas Jaekel } 521f2dd45e5SAndreas Jaekel 522f2dd45e5SAndreas Jaekel static void 523aafc540fSAndreas Jaekel zev_print_event(char *buf, int len) 524aafc540fSAndreas Jaekel { 525f2dd45e5SAndreas Jaekel int record_len; 526f2dd45e5SAndreas Jaekel int op; 527aafc540fSAndreas Jaekel 528f2dd45e5SAndreas Jaekel record_len = *(uint32_t *)buf; 529f2dd45e5SAndreas Jaekel if (record_len != len) { 530f2dd45e5SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 531f2dd45e5SAndreas Jaekel record_len, len); 532aafc540fSAndreas Jaekel exit(1); 533aafc540fSAndreas Jaekel } 534f2dd45e5SAndreas Jaekel op = *((uint32_t *)buf + 1); 535aafc540fSAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 536f2dd45e5SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 537aafc540fSAndreas Jaekel exit(1); 538aafc540fSAndreas Jaekel } 539f2dd45e5SAndreas Jaekel switch (op) { 540f2dd45e5SAndreas Jaekel case ZEV_OP_ERROR: 541f2dd45e5SAndreas Jaekel zev_print_error(buf); 542aafc540fSAndreas Jaekel break; 543888fea18SAndreas Jaekel case ZEV_OP_MARK: 544888fea18SAndreas Jaekel zev_print_mark(buf); 545888fea18SAndreas Jaekel break; 546f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 547f2dd45e5SAndreas Jaekel zev_print_zfs_mount(buf); 548aafc540fSAndreas Jaekel break; 549f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 550f2dd45e5SAndreas Jaekel zev_print_zfs_umount(buf); 551aafc540fSAndreas Jaekel break; 552f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 553f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 554aafc540fSAndreas Jaekel break; 555f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 556f2dd45e5SAndreas Jaekel zev_print_zvol_write(buf); 557f2dd45e5SAndreas Jaekel break; 558f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 559f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(buf); 560f2dd45e5SAndreas Jaekel break; 561f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 562f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 563f2dd45e5SAndreas Jaekel break; 564f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 565f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(buf); 566f2dd45e5SAndreas Jaekel break; 567f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 568f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 569f2dd45e5SAndreas Jaekel break; 570f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 571f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 572f2dd45e5SAndreas Jaekel break; 573f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 574f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(buf); 575f2dd45e5SAndreas Jaekel break; 576f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 577f2dd45e5SAndreas Jaekel zev_print_znode_link(buf); 578f2dd45e5SAndreas Jaekel break; 579f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 580f2dd45e5SAndreas Jaekel zev_print_znode_symlink(buf); 581f2dd45e5SAndreas Jaekel break; 582f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 583f2dd45e5SAndreas Jaekel zev_print_znode_rename(buf); 584f2dd45e5SAndreas Jaekel break; 585f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 586f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 587f2dd45e5SAndreas Jaekel break; 588f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 589f2dd45e5SAndreas Jaekel zev_print_znode_truncate(buf); 590f2dd45e5SAndreas Jaekel break; 591f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 592f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 593f2dd45e5SAndreas Jaekel break; 594f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 595f2dd45e5SAndreas Jaekel zev_print_znode_acl(buf); 596aafc540fSAndreas Jaekel break; 597aafc540fSAndreas Jaekel default: 598f2dd45e5SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 599aafc540fSAndreas Jaekel exit(1); 600aafc540fSAndreas Jaekel } 601aafc540fSAndreas Jaekel } 602aafc540fSAndreas Jaekel 603add9520fSAndreas Jaekel static int 6046a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 605a18c35b9SAndreas Jaekel { 606a18c35b9SAndreas Jaekel struct pollfd pfd[1]; 607a18c35b9SAndreas Jaekel int ret; 608aafc540fSAndreas Jaekel char buf[4096]; 609d979f56cSAndreas Jaekel zev_event_t *ev; 610d979f56cSAndreas Jaekel int off = 0; 611add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 612add9520fSAndreas Jaekel int q_fd; 613add9520fSAndreas Jaekel 6146a6a51eeSAndreas Jaekel if (create_tmp_queue) { 615add9520fSAndreas Jaekel aq.zev_max_queue_len = 0; 616add9520fSAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 617add9520fSAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 618add9520fSAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 619add9520fSAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 620add9520fSAndreas Jaekel 621add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 622add9520fSAndreas Jaekel perror("adding temporary queue failed"); 623add9520fSAndreas Jaekel return (EXIT_FAILURE); 624add9520fSAndreas Jaekel } 625add9520fSAndreas Jaekel 6266a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 6276a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 628add9520fSAndreas Jaekel q_fd = open(buf, O_RDONLY); 629add9520fSAndreas Jaekel if (q_fd < 0) { 630add9520fSAndreas Jaekel perror("opening queue device failed"); 631add9520fSAndreas Jaekel return (EXIT_FAILURE); 632add9520fSAndreas Jaekel } 6336a6a51eeSAndreas Jaekel } else { 6346a6a51eeSAndreas Jaekel q_fd = fd; 6356a6a51eeSAndreas Jaekel } 636add9520fSAndreas Jaekel 637a18c35b9SAndreas Jaekel while (1) { 638add9520fSAndreas Jaekel pfd[0].fd = q_fd; 639a18c35b9SAndreas Jaekel pfd[0].events = POLLIN; 640a18c35b9SAndreas Jaekel ret = poll(pfd, 1, 1000); 641a18c35b9SAndreas Jaekel if (ret < 0) { 642a18c35b9SAndreas Jaekel perror("poll failed"); 6436a6a51eeSAndreas Jaekel close(q_fd); 644add9520fSAndreas Jaekel return(EXIT_FAILURE); 645a18c35b9SAndreas Jaekel } 646a18c35b9SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 647a18c35b9SAndreas Jaekel continue; 648a18c35b9SAndreas Jaekel /* data available */ 649add9520fSAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 650a18c35b9SAndreas Jaekel if (ret < 0) { 651a18c35b9SAndreas Jaekel perror("read failed"); 6526a6a51eeSAndreas Jaekel close(q_fd); 653add9520fSAndreas Jaekel return(EXIT_FAILURE); 654a18c35b9SAndreas Jaekel } 655a18c35b9SAndreas Jaekel if (ret == 0) 656a18c35b9SAndreas Jaekel continue; 657d979f56cSAndreas Jaekel while (ret > off) { 658d979f56cSAndreas Jaekel ev = (zev_event_t *)(buf + off); 659d979f56cSAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 660d979f56cSAndreas Jaekel off += ev->header.record_len; 661d979f56cSAndreas Jaekel } 662149d0affSAndreas Jaekel off = 0; 663a18c35b9SAndreas Jaekel } 6646a6a51eeSAndreas Jaekel if (create_tmp_queue) 665add9520fSAndreas Jaekel close(q_fd); 666add9520fSAndreas Jaekel return EXIT_SUCCESS; 667a18c35b9SAndreas Jaekel } 668a18c35b9SAndreas Jaekel 669a18c35b9SAndreas Jaekel static void 670a18c35b9SAndreas Jaekel usage(char *progname) 671a18c35b9SAndreas Jaekel { 672add9520fSAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 673add9520fSAndreas Jaekel fprintf(stderr, "\n"); 674add9520fSAndreas Jaekel fprintf(stderr, " Status information:\n"); 675a18c35b9SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 676a18c35b9SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 677add9520fSAndreas Jaekel fprintf(stderr, " -D print zev module debug " 678add9520fSAndreas Jaekel "information\n"); 679add9520fSAndreas Jaekel fprintf(stderr, "\n"); 680add9520fSAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 681add9520fSAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 682add9520fSAndreas Jaekel "length\n"); 683add9520fSAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 684add9520fSAndreas Jaekel "this pool\n"); 685a18c35b9SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 686add9520fSAndreas Jaekel fprintf(stderr, "\n"); 687add9520fSAndreas Jaekel fprintf(stderr, " Queue management:\n"); 688add9520fSAndreas Jaekel fprintf(stderr, " -l list queues\n"); 6896a6a51eeSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 6906a6a51eeSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 691add9520fSAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 692add9520fSAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 693add9520fSAndreas Jaekel "(default)\n"); 694add9520fSAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 695add9520fSAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 6966a6a51eeSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 697add9520fSAndreas Jaekel "length\n"); 698add9520fSAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 699add9520fSAndreas Jaekel "throttle\n"); 700add9520fSAndreas Jaekel fprintf(stderr, "\n"); 701add9520fSAndreas Jaekel fprintf(stderr, " Other options:\n"); 702add9520fSAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 703add9520fSAndreas Jaekel "('%s')\n", ZEV_DEVICE); 7046a6a51eeSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 7056a6a51eeSAndreas Jaekel "queue name\n"); 706888fea18SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 70742110aacSAndreas Jaekel fprintf(stderr, " -c <filename> list file's content " 70842110aacSAndreas Jaekel "checksums\n"); 709*16ff6b2fSAndreas Jaekel fprintf(stderr, " -v verbose: additional output " 710205ed6bfSAndreas Jaekel "for some operations\n"); 711*16ff6b2fSAndreas Jaekel fprintf(stderr, " -g grep-friendly event output, " 712*16ff6b2fSAndreas Jaekel "one event per line\n"); 713a18c35b9SAndreas Jaekel exit (EXIT_FAILURE); 714a18c35b9SAndreas Jaekel } 715a18c35b9SAndreas Jaekel 716a18c35b9SAndreas Jaekel static int 7176a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 718a18c35b9SAndreas Jaekel { 719add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 720add9520fSAndreas Jaekel int namelen; 721a18c35b9SAndreas Jaekel 722add9520fSAndreas Jaekel namelen = strlen(arg); 723add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 724add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 725a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 726a18c35b9SAndreas Jaekel } 727add9520fSAndreas Jaekel 728add9520fSAndreas Jaekel aq.zev_namelen = namelen; 729add9520fSAndreas Jaekel strcpy(aq.zev_name, arg); 7306a6a51eeSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 7316a6a51eeSAndreas Jaekel if (blocking) { 7326a6a51eeSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 7336a6a51eeSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 7346a6a51eeSAndreas Jaekel } else { 735add9520fSAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 7366a6a51eeSAndreas Jaekel } 737add9520fSAndreas Jaekel 738add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 739add9520fSAndreas Jaekel perror("adding queue failed"); 740a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 741a18c35b9SAndreas Jaekel } 742a18c35b9SAndreas Jaekel return (0); 743a18c35b9SAndreas Jaekel } 744a18c35b9SAndreas Jaekel 745a18c35b9SAndreas Jaekel static int 746add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg) 747fec460f8SAndreas Jaekel { 748add9520fSAndreas Jaekel zev_ioctl_remove_queue_t aq; 749add9520fSAndreas Jaekel int namelen; 750fec460f8SAndreas Jaekel 751add9520fSAndreas Jaekel namelen = strlen(arg); 752add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 753add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 754fec460f8SAndreas Jaekel return (EXIT_FAILURE); 755fec460f8SAndreas Jaekel } 756add9520fSAndreas Jaekel 7576a6a51eeSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 7586a6a51eeSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 759add9520fSAndreas Jaekel 760add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 761add9520fSAndreas Jaekel perror("removing queue failed"); 762add9520fSAndreas Jaekel return (EXIT_FAILURE); 763add9520fSAndreas Jaekel } 764add9520fSAndreas Jaekel return (0); 765add9520fSAndreas Jaekel } 766add9520fSAndreas Jaekel 767add9520fSAndreas Jaekel static int 768add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 769add9520fSAndreas Jaekel { 770add9520fSAndreas Jaekel uint64_t maxqueuelen; 771add9520fSAndreas Jaekel 772add9520fSAndreas Jaekel errno = 0; 773add9520fSAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 774add9520fSAndreas Jaekel if (errno) { 775add9520fSAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 776add9520fSAndreas Jaekel return (EXIT_FAILURE); 777add9520fSAndreas Jaekel } 778add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 779add9520fSAndreas Jaekel perror("setting max queue length failed"); 780fec460f8SAndreas Jaekel return (EXIT_FAILURE); 781fec460f8SAndreas Jaekel } 782fec460f8SAndreas Jaekel return (0); 783fec460f8SAndreas Jaekel } 784fec460f8SAndreas Jaekel 785fec460f8SAndreas Jaekel static int 786a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 787a18c35b9SAndreas Jaekel { 788a18c35b9SAndreas Jaekel zev_ioctl_poolarg_t pa; 789a18c35b9SAndreas Jaekel int len; 790a18c35b9SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 791a18c35b9SAndreas Jaekel len = strlen(poolname); 792a18c35b9SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 793a18c35b9SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 794a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 795a18c35b9SAndreas Jaekel } 796a18c35b9SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 797a18c35b9SAndreas Jaekel pa.zev_poolname_len = len; 798a18c35b9SAndreas Jaekel if (ioctl(fd, op, &pa)) { 799a18c35b9SAndreas Jaekel perror("muting pool data failed"); 800a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 801a18c35b9SAndreas Jaekel } 802a18c35b9SAndreas Jaekel return (0); 803a18c35b9SAndreas Jaekel } 804a18c35b9SAndreas Jaekel 805a18c35b9SAndreas Jaekel int 806a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 807a18c35b9SAndreas Jaekel { 808a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 809a18c35b9SAndreas Jaekel } 810a18c35b9SAndreas Jaekel 811a18c35b9SAndreas Jaekel int 812a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 813a18c35b9SAndreas Jaekel { 814a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 815a18c35b9SAndreas Jaekel } 816a18c35b9SAndreas Jaekel 817888fea18SAndreas Jaekel static int 818add9520fSAndreas Jaekel zev_debug_info(int fd) 819add9520fSAndreas Jaekel { 820add9520fSAndreas Jaekel zev_ioctl_debug_info_t di; 821add9520fSAndreas Jaekel 822add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 823add9520fSAndreas Jaekel perror("getting zev debug info failed"); 824add9520fSAndreas Jaekel return (EXIT_FAILURE); 825add9520fSAndreas Jaekel } 826add9520fSAndreas Jaekel 827add9520fSAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 828205ed6bfSAndreas Jaekel printf("checksum cache size: %llu\n", di.zev_chksum_cache_size); 829205ed6bfSAndreas Jaekel printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits); 830205ed6bfSAndreas Jaekel printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses); 831add9520fSAndreas Jaekel return 0; 832add9520fSAndreas Jaekel } 833add9520fSAndreas Jaekel 834add9520fSAndreas Jaekel static int 835888fea18SAndreas Jaekel zev_mark(int fd, char *arg) 836888fea18SAndreas Jaekel { 837888fea18SAndreas Jaekel zev_ioctl_mark_t *mark; 838888fea18SAndreas Jaekel uint64_t guid; 839888fea18SAndreas Jaekel int len; 840888fea18SAndreas Jaekel char *p; 841888fea18SAndreas Jaekel 842888fea18SAndreas Jaekel p = strchr(arg, ':'); 843888fea18SAndreas Jaekel if (!p) { 844888fea18SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 845888fea18SAndreas Jaekel "e.g. '123:hello'\n"); 846888fea18SAndreas Jaekel exit (EXIT_FAILURE); 847888fea18SAndreas Jaekel } 848888fea18SAndreas Jaekel *p = '\n'; 849888fea18SAndreas Jaekel p++; 850888fea18SAndreas Jaekel 851888fea18SAndreas Jaekel errno = 0; 852add9520fSAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 853888fea18SAndreas Jaekel if (errno) { 854888fea18SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 855888fea18SAndreas Jaekel exit (EXIT_FAILURE); 856888fea18SAndreas Jaekel } 857888fea18SAndreas Jaekel 858888fea18SAndreas Jaekel len = strlen(p); 859888fea18SAndreas Jaekel 860888fea18SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 861888fea18SAndreas Jaekel if (!mark) { 862888fea18SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 863888fea18SAndreas Jaekel strerror(errno)); 864888fea18SAndreas Jaekel exit (EXIT_FAILURE); 865888fea18SAndreas Jaekel } 866888fea18SAndreas Jaekel mark->zev_guid = guid; 867888fea18SAndreas Jaekel mark->zev_mark_id = 0; 868888fea18SAndreas Jaekel mark->zev_payload_len = len; 869888fea18SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 870888fea18SAndreas Jaekel 871888fea18SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 872888fea18SAndreas Jaekel perror("queueing mark failed"); 873888fea18SAndreas Jaekel return (EXIT_FAILURE); 874888fea18SAndreas Jaekel } 875888fea18SAndreas Jaekel 876888fea18SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 877888fea18SAndreas Jaekel return (0); 878888fea18SAndreas Jaekel } 879888fea18SAndreas Jaekel 880add9520fSAndreas Jaekel static int 881add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 882add9520fSAndreas Jaekel { 883add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 884add9520fSAndreas Jaekel 8856a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 8866a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 887add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 888add9520fSAndreas Jaekel return EXIT_FAILURE; 889add9520fSAndreas Jaekel } 8906a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 891add9520fSAndreas Jaekel 892add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 893add9520fSAndreas Jaekel perror("getting queue properties failed"); 894add9520fSAndreas Jaekel return (EXIT_FAILURE); 895add9520fSAndreas Jaekel } 896add9520fSAndreas Jaekel if (block) { 897add9520fSAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 898add9520fSAndreas Jaekel } else { 899add9520fSAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 900add9520fSAndreas Jaekel } 901add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 902add9520fSAndreas Jaekel perror("setting queue properties failed"); 903add9520fSAndreas Jaekel return (EXIT_FAILURE); 904add9520fSAndreas Jaekel } 905add9520fSAndreas Jaekel return (0); 906add9520fSAndreas Jaekel } 907add9520fSAndreas Jaekel 908add9520fSAndreas Jaekel static int 909add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 910add9520fSAndreas Jaekel { 911add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 912add9520fSAndreas Jaekel 913add9520fSAndreas Jaekel if (!len) { 914add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 915add9520fSAndreas Jaekel return EXIT_FAILURE; 916add9520fSAndreas Jaekel } 917add9520fSAndreas Jaekel 9186a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9196a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 920add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 921add9520fSAndreas Jaekel return EXIT_FAILURE; 922add9520fSAndreas Jaekel } 9236a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 924add9520fSAndreas Jaekel 925add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 926add9520fSAndreas Jaekel perror("getting queue properties failed"); 927add9520fSAndreas Jaekel return (EXIT_FAILURE); 928add9520fSAndreas Jaekel } 929add9520fSAndreas Jaekel gqp.zev_max_queue_len = atol(len); 930add9520fSAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 931add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 932add9520fSAndreas Jaekel return (EXIT_FAILURE); 933add9520fSAndreas Jaekel } 934add9520fSAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 935add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 936add9520fSAndreas Jaekel return (EXIT_FAILURE); 937add9520fSAndreas Jaekel } 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_poll_wakeup_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, "poll throttle 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_poll_wakeup_threshold = atol(len); 968add9520fSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 969add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 970add9520fSAndreas Jaekel return (EXIT_FAILURE); 971add9520fSAndreas Jaekel } 9726a6a51eeSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 973add9520fSAndreas Jaekel fprintf(stderr, "poll throttle 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_queue_properties(int fd, char *arg) 986add9520fSAndreas Jaekel { 987add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 988add9520fSAndreas Jaekel 9896a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 9906a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 991add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 992add9520fSAndreas Jaekel return EXIT_FAILURE; 993add9520fSAndreas Jaekel } 9946a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 995add9520fSAndreas Jaekel 996add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 997add9520fSAndreas Jaekel perror("getting queue properties failed"); 998add9520fSAndreas Jaekel return (EXIT_FAILURE); 999add9520fSAndreas Jaekel } 1000add9520fSAndreas Jaekel 1001add9520fSAndreas Jaekel printf("queue : %s\n", arg); 1002add9520fSAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 1003add9520fSAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 1004add9520fSAndreas Jaekel printf("persistent : %s\n", 1005add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 1006add9520fSAndreas Jaekel printf("blocking : %s\n", 1007add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 1008add9520fSAndreas Jaekel 1009add9520fSAndreas Jaekel return (0); 1010add9520fSAndreas Jaekel } 1011add9520fSAndreas Jaekel 1012add9520fSAndreas Jaekel static int 1013add9520fSAndreas Jaekel zev_list_queues(int fd) 1014add9520fSAndreas Jaekel { 1015add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 1016add9520fSAndreas Jaekel zev_ioctl_get_queue_list_t gql; 1017add9520fSAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 1018add9520fSAndreas Jaekel uint64_t i; 1019add9520fSAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 1020add9520fSAndreas Jaekel 1021add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 1022add9520fSAndreas Jaekel perror("getting queue list failed"); 1023add9520fSAndreas Jaekel return (EXIT_FAILURE); 1024add9520fSAndreas Jaekel } 1025add9520fSAndreas Jaekel 1026add9520fSAndreas Jaekel printf("Name Size " 1027add9520fSAndreas Jaekel "Max Size Wakeup Per Block\n"); 1028add9520fSAndreas Jaekel 1029add9520fSAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 1030add9520fSAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 1031add9520fSAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 1032add9520fSAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 1033add9520fSAndreas Jaekel 10346a6a51eeSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 10356a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10366a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 10376a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1038add9520fSAndreas Jaekel 1039add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 1040add9520fSAndreas Jaekel if (errno == ENOENT) 1041add9520fSAndreas Jaekel continue; 1042add9520fSAndreas Jaekel perror("getting queue properties failed"); 1043add9520fSAndreas Jaekel return (EXIT_FAILURE); 1044add9520fSAndreas Jaekel } 1045add9520fSAndreas Jaekel 10466a6a51eeSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 10476a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 10486a6a51eeSAndreas Jaekel gs.zev_queue_name.zev_namelen = 10496a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 1050add9520fSAndreas Jaekel 1051add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 1052add9520fSAndreas Jaekel if (errno == ENOENT) 1053add9520fSAndreas Jaekel continue; 1054add9520fSAndreas Jaekel perror("getting statistics data failed"); 1055add9520fSAndreas Jaekel return (EXIT_FAILURE); 1056add9520fSAndreas Jaekel } 1057add9520fSAndreas Jaekel 1058add9520fSAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 1059add9520fSAndreas Jaekel " %-3s %-3s\n", 1060add9520fSAndreas Jaekel name, 1061add9520fSAndreas Jaekel gs.zev_statistics.zev_queue_len, 1062add9520fSAndreas Jaekel gqp.zev_max_queue_len, 1063add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold, 1064add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 1065add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 1066add9520fSAndreas Jaekel "yes" : "no"); 1067add9520fSAndreas Jaekel } 1068add9520fSAndreas Jaekel 1069add9520fSAndreas Jaekel return (0); 1070add9520fSAndreas Jaekel } 1071add9520fSAndreas Jaekel 107242110aacSAndreas Jaekel static int 107342110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename) 107442110aacSAndreas Jaekel { 107542110aacSAndreas Jaekel int fd; 107642110aacSAndreas Jaekel offset_t off; 107742110aacSAndreas Jaekel offset_t data; 107842110aacSAndreas Jaekel zev_sig_t *sig; 107942110aacSAndreas Jaekel char *buf; 108042110aacSAndreas Jaekel zev_ioctl_get_signatures_t *gs; 108142110aacSAndreas Jaekel int i; 108242110aacSAndreas Jaekel char sigval[(SHA1_DIGEST_LENGTH * 2) + 1]; 108342110aacSAndreas Jaekel int buf_size; 108442110aacSAndreas Jaekel 108542110aacSAndreas Jaekel /* control struct, one lv1 signature and up to 256 lv0 signatures */ 108642110aacSAndreas Jaekel buf_size = (1 + 256) * sizeof(zev_sig_t); 108742110aacSAndreas Jaekel buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size); 108842110aacSAndreas Jaekel if (!buf) { 108942110aacSAndreas Jaekel perror("can't allocate checksum buffer"); 109042110aacSAndreas Jaekel return (EXIT_FAILURE); 109142110aacSAndreas Jaekel } 109242110aacSAndreas Jaekel 109342110aacSAndreas Jaekel fd = open(filename, O_RDONLY); 109442110aacSAndreas Jaekel if (fd < 0) { 109542110aacSAndreas Jaekel perror("can't open file"); 109642110aacSAndreas Jaekel return (EXIT_FAILURE); 109742110aacSAndreas Jaekel } 109842110aacSAndreas Jaekel 109942110aacSAndreas Jaekel gs = (zev_ioctl_get_signatures_t *)buf; 110042110aacSAndreas Jaekel gs->zev_fd = fd; 110142110aacSAndreas Jaekel gs->zev_bufsize = buf_size; 110242110aacSAndreas Jaekel 110342110aacSAndreas Jaekel off = 0; 110442110aacSAndreas Jaekel data = 0; 110542110aacSAndreas Jaekel while (1) { 110642110aacSAndreas Jaekel errno = 0; 110742110aacSAndreas Jaekel data = llseek(fd, off, SEEK_DATA); 110842110aacSAndreas Jaekel if (data < 0) { 110942110aacSAndreas Jaekel if (errno == ENXIO) /* no more data */ 111042110aacSAndreas Jaekel break; 111142110aacSAndreas Jaekel perror("llseek failed"); 111242110aacSAndreas Jaekel goto err; 111342110aacSAndreas Jaekel } 111442110aacSAndreas Jaekel data = P2ALIGN(data, ZEV_L1_SIZE); 111542110aacSAndreas Jaekel off = data + ZEV_L1_SIZE; 111642110aacSAndreas Jaekel 111742110aacSAndreas Jaekel gs->zev_offset = data; 111842110aacSAndreas Jaekel gs->zev_len = ZEV_L1_SIZE; 111942110aacSAndreas Jaekel 112042110aacSAndreas Jaekel if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) { 112142110aacSAndreas Jaekel perror("ioctl to get signatures failed"); 112242110aacSAndreas Jaekel goto err; 112342110aacSAndreas Jaekel } 112442110aacSAndreas Jaekel 112542110aacSAndreas Jaekel for (i=0; i<gs->zev_signature_cnt; i++) { 112642110aacSAndreas Jaekel sig = (zev_sig_t *)ZEV_SIGNATURES(gs); 112742110aacSAndreas Jaekel sig += i; 112842110aacSAndreas Jaekel sig2hex_direct(sig->value, sigval); 112942110aacSAndreas Jaekel printf("level %d, offset %llu, value %s\n", 113042110aacSAndreas Jaekel sig->level, sig->block_offset, sigval); 113142110aacSAndreas Jaekel } 113242110aacSAndreas Jaekel } 113342110aacSAndreas Jaekel 113442110aacSAndreas Jaekel free(buf); 113542110aacSAndreas Jaekel close(fd); 113642110aacSAndreas Jaekel return 0; 113742110aacSAndreas Jaekel err: 113842110aacSAndreas Jaekel free(buf); 113942110aacSAndreas Jaekel close(fd); 114042110aacSAndreas Jaekel return (EXIT_FAILURE); 114142110aacSAndreas Jaekel } 114242110aacSAndreas Jaekel 1143a18c35b9SAndreas Jaekel int 1144a18c35b9SAndreas Jaekel main(int argc, char **argv) 1145a18c35b9SAndreas Jaekel { 1146a18c35b9SAndreas Jaekel int fd; 1147a18c35b9SAndreas Jaekel int c; 1148a18c35b9SAndreas Jaekel extern char *optarg; 11496a6a51eeSAndreas Jaekel int create_tmp_queue = 1; 11506a6a51eeSAndreas Jaekel char buf[MAXPATHLEN]; 1151a18c35b9SAndreas Jaekel 1152a18c35b9SAndreas Jaekel /* open device */ 1153a18c35b9SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1154a18c35b9SAndreas Jaekel if (fd < 0) { 1155a18c35b9SAndreas Jaekel perror("opening zev device failed"); 1156a18c35b9SAndreas Jaekel return EXIT_FAILURE; 1157a18c35b9SAndreas Jaekel } 11586a6a51eeSAndreas Jaekel while ((c = getopt(argc, argv, 1159*16ff6b2fSAndreas Jaekel "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 1160a18c35b9SAndreas Jaekel switch(c) { 1161*16ff6b2fSAndreas Jaekel case 'g': 1162*16ff6b2fSAndreas Jaekel grep_friendly++; 1163*16ff6b2fSAndreas Jaekel verbose++; 1164*16ff6b2fSAndreas Jaekel break; 1165205ed6bfSAndreas Jaekel case 'v': 1166205ed6bfSAndreas Jaekel verbose++; 1167205ed6bfSAndreas Jaekel break; 1168a18c35b9SAndreas Jaekel case 's': 1169add9520fSAndreas Jaekel return zev_statistics(fd); 1170a18c35b9SAndreas Jaekel case 'p': 11716a6a51eeSAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 117242110aacSAndreas Jaekel case 'c': 117342110aacSAndreas Jaekel return zev_checksum(fd, optarg); 1174add9520fSAndreas Jaekel case 'D': 1175add9520fSAndreas Jaekel return zev_debug_info(fd); 1176a18c35b9SAndreas Jaekel case 'd': 1177add9520fSAndreas Jaekel close(fd); 1178a18c35b9SAndreas Jaekel zev_device = optarg; 1179add9520fSAndreas Jaekel fd = open(zev_device, O_RDONLY); 1180add9520fSAndreas Jaekel if (fd < 0) { 1181add9520fSAndreas Jaekel perror("opening zev device failed"); 1182add9520fSAndreas Jaekel return EXIT_FAILURE; 1183add9520fSAndreas Jaekel } 11846a6a51eeSAndreas Jaekel create_tmp_queue = 0; 11856a6a51eeSAndreas Jaekel break; 11866a6a51eeSAndreas Jaekel case 'q': 11876a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 11886a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 11896a6a51eeSAndreas Jaekel close(fd); 11906a6a51eeSAndreas Jaekel zev_device = buf; 11916a6a51eeSAndreas Jaekel fd = open(zev_device, O_RDONLY); 11926a6a51eeSAndreas Jaekel if (fd < 0) { 11936a6a51eeSAndreas Jaekel perror("opening zev device failed"); 11946a6a51eeSAndreas Jaekel return EXIT_FAILURE; 11956a6a51eeSAndreas Jaekel } 11966a6a51eeSAndreas Jaekel create_tmp_queue = 0; 1197a18c35b9SAndreas Jaekel break; 1198add9520fSAndreas Jaekel case 'l': 1199add9520fSAndreas Jaekel return zev_list_queues(fd); 1200add9520fSAndreas Jaekel case 'Q': 1201add9520fSAndreas Jaekel return zev_set_global_max_queue_len(fd, optarg); 12026a6a51eeSAndreas Jaekel case 'L': 1203add9520fSAndreas Jaekel return zev_set_max_queue_len(fd, optarg, argv[optind]); 1204fec460f8SAndreas Jaekel case 't': 1205add9520fSAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg, 1206add9520fSAndreas Jaekel argv[optind]); 1207a18c35b9SAndreas Jaekel case 'm': 1208a18c35b9SAndreas Jaekel return zev_mute_pool(fd, optarg); 1209a18c35b9SAndreas Jaekel case 'M': 1210a18c35b9SAndreas Jaekel return zev_unmute_pool(fd, optarg); 1211888fea18SAndreas Jaekel case 'k': 1212888fea18SAndreas Jaekel return zev_mark(fd, optarg); 1213add9520fSAndreas Jaekel case 'a': 12146a6a51eeSAndreas Jaekel return zev_add_queue(fd, optarg, 0); 12156a6a51eeSAndreas Jaekel case 'A': 12166a6a51eeSAndreas Jaekel return zev_add_queue(fd, optarg, 1); 1217add9520fSAndreas Jaekel case 'r': 1218add9520fSAndreas Jaekel return zev_remove_queue(fd, optarg); 1219add9520fSAndreas Jaekel case 'b': 1220add9520fSAndreas Jaekel return zev_queue_blocking(fd, optarg, 0); 1221add9520fSAndreas Jaekel case 'B': 1222add9520fSAndreas Jaekel return zev_queue_blocking(fd, optarg, 1); 1223add9520fSAndreas Jaekel case 'P': 1224add9520fSAndreas Jaekel return zev_queue_properties(fd, optarg); 1225a18c35b9SAndreas Jaekel case 'h': 1226a18c35b9SAndreas Jaekel case '?': 1227a18c35b9SAndreas Jaekel default: 1228a18c35b9SAndreas Jaekel usage(argv[0]); 1229a18c35b9SAndreas Jaekel } 1230a18c35b9SAndreas Jaekel } 1231a18c35b9SAndreas Jaekel usage(argv[0]); 1232a18c35b9SAndreas Jaekel close(fd); 1233add9520fSAndreas Jaekel return EXIT_FAILURE; 1234a18c35b9SAndreas Jaekel } 1235a18c35b9SAndreas Jaekel 1236