12bb8e5e2SAndreas Jaekel #include <stdio.h> 22bb8e5e2SAndreas Jaekel #include <unistd.h> 32bb8e5e2SAndreas Jaekel #include <stdlib.h> 42bb8e5e2SAndreas Jaekel #include <fcntl.h> 52bb8e5e2SAndreas Jaekel #include <stropts.h> 62bb8e5e2SAndreas Jaekel #include <poll.h> 72bb8e5e2SAndreas Jaekel #include <string.h> 82bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h> 92bb8e5e2SAndreas Jaekel #include <errno.h> 102bb8e5e2SAndreas Jaekel 112bb8e5e2SAndreas Jaekel #define OP_STATISTICS (1 << 0) 122bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS (1 << 1) 132bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL (1 << 2) 142bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL (1 << 3) 152bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN (1 << 4) 162bb8e5e2SAndreas Jaekel 172bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev" 182bb8e5e2SAndreas Jaekel 192bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 202bb8e5e2SAndreas Jaekel 219193e9c2SAndreas Jaekel static char *zev_op_name[] = { 229193e9c2SAndreas Jaekel "ZEV_OP_ERROR", 239193e9c2SAndreas Jaekel "ZEV_OP_ZFS_MOUNT", 249193e9c2SAndreas Jaekel "ZEV_OP_ZFS_UMOUNT", 259193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_WRITE", 269193e9c2SAndreas Jaekel "ZEV_OP_ZVOL_TRUNCATE", 279193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 289193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_CREATE", 299193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MKDIR", 309193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 319193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_REMOVE", 329193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RMDIR", 339193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_LINK", 349193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SYMLINK", 359193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_RENAME", 369193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_WRITE", 379193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_TRUNCATE", 389193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_SETATTR", 399193e9c2SAndreas Jaekel "ZEV_OP_ZNODE_ACL", 409193e9c2SAndreas Jaekel NULL 419193e9c2SAndreas Jaekel }; 429193e9c2SAndreas Jaekel 432bb8e5e2SAndreas Jaekel static void 442bb8e5e2SAndreas Jaekel zev_statistics(int fd) 452bb8e5e2SAndreas Jaekel { 462bb8e5e2SAndreas Jaekel zev_statistics_t zs; 472bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) { 482bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 492bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 502bb8e5e2SAndreas Jaekel } 512bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 522bb8e5e2SAndreas Jaekel 532bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 542bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 55205a9bc9SAndreas Jaekel printf(" poll wakeup throttle : %lu\n\n", 56205a9bc9SAndreas Jaekel zs.zev_poll_wakeup_queue_len); 572bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 582bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 592bb8e5e2SAndreas Jaekel 602bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 612bb8e5e2SAndreas Jaekel 622bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 632bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 642bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 652bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 662bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 672bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 682bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 692bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 702bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 712bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 722bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 732bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 742bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 752bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 762bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 772bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 782bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 792bb8e5e2SAndreas Jaekel } 802bb8e5e2SAndreas Jaekel 812bb8e5e2SAndreas Jaekel static void 82*63aba447SAndreas Jaekel zev_print_error(char *buf) 83*63aba447SAndreas Jaekel { 84*63aba447SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 85*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 86*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 87*63aba447SAndreas Jaekel 88*63aba447SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 89*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 90*63aba447SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 91*63aba447SAndreas Jaekel } 92*63aba447SAndreas Jaekel 93*63aba447SAndreas Jaekel static void 94*63aba447SAndreas Jaekel zev_print_zfs_mount(char *buf) 95*63aba447SAndreas Jaekel { 96*63aba447SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 97*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 98*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 99*63aba447SAndreas Jaekel 100*63aba447SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 101*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 102*63aba447SAndreas Jaekel rec->guid, 103*63aba447SAndreas Jaekel rec->remount ? "true" : "false", 104*63aba447SAndreas Jaekel ZEV_DATASET(rec), 105*63aba447SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 106*63aba447SAndreas Jaekel } 107*63aba447SAndreas Jaekel 108*63aba447SAndreas Jaekel static void 109*63aba447SAndreas Jaekel zev_print_zfs_umount(char *buf) 110*63aba447SAndreas Jaekel { 111*63aba447SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 112*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 113*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 114*63aba447SAndreas Jaekel 115*63aba447SAndreas Jaekel printf("%s %s: guid=%llu\n", 116*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 117*63aba447SAndreas Jaekel rec->guid); 118*63aba447SAndreas Jaekel } 119*63aba447SAndreas Jaekel 120*63aba447SAndreas Jaekel static void 121*63aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf) 122*63aba447SAndreas Jaekel { 123*63aba447SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 124*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 125*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 126*63aba447SAndreas Jaekel 127*63aba447SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 128*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 129*63aba447SAndreas Jaekel rec->guid, 130*63aba447SAndreas Jaekel rec->offset, 131*63aba447SAndreas Jaekel rec->length); 132*63aba447SAndreas Jaekel } 133*63aba447SAndreas Jaekel 134*63aba447SAndreas Jaekel static void 135*63aba447SAndreas Jaekel zev_print_zvol_write(char *buf) 136*63aba447SAndreas Jaekel { 137*63aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 138*63aba447SAndreas Jaekel } 139*63aba447SAndreas Jaekel 140*63aba447SAndreas Jaekel static void 141*63aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 142*63aba447SAndreas Jaekel { 143*63aba447SAndreas Jaekel zev_znode_close_after_update_t *rec = 144*63aba447SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 145*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 146*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 147*63aba447SAndreas Jaekel 148*63aba447SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 149*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 150*63aba447SAndreas Jaekel rec->guid, 151*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 152*63aba447SAndreas Jaekel } 153*63aba447SAndreas Jaekel 154*63aba447SAndreas Jaekel static void 155*63aba447SAndreas Jaekel zev_print_znode_create(char *buf) 156*63aba447SAndreas Jaekel { 157*63aba447SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 158*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 159*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 160*63aba447SAndreas Jaekel 161*63aba447SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu name='%s'\n", 162*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 163*63aba447SAndreas Jaekel rec->guid, 164*63aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 165*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 166*63aba447SAndreas Jaekel ZEV_NAME(rec)); 167*63aba447SAndreas Jaekel } 168*63aba447SAndreas Jaekel 169*63aba447SAndreas Jaekel static void 170*63aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf) 171*63aba447SAndreas Jaekel { 172*63aba447SAndreas Jaekel zev_print_znode_create(buf); 173*63aba447SAndreas Jaekel } 174*63aba447SAndreas Jaekel 175*63aba447SAndreas Jaekel static void 176*63aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 177*63aba447SAndreas Jaekel { 178*63aba447SAndreas Jaekel zev_print_znode_create(buf); 179*63aba447SAndreas Jaekel } 180*63aba447SAndreas Jaekel 181*63aba447SAndreas Jaekel static void 182*63aba447SAndreas Jaekel zev_print_znode_remove(char *buf) 183*63aba447SAndreas Jaekel { 184*63aba447SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 185*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 186*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 187*63aba447SAndreas Jaekel 188*63aba447SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu name='%s'\n", 189*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 190*63aba447SAndreas Jaekel rec->guid, 191*63aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 192*63aba447SAndreas Jaekel ZEV_NAME(rec)); 193*63aba447SAndreas Jaekel } 194*63aba447SAndreas Jaekel 195*63aba447SAndreas Jaekel static void 196*63aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf) 197*63aba447SAndreas Jaekel { 198*63aba447SAndreas Jaekel zev_print_znode_remove(buf); 199*63aba447SAndreas Jaekel } 200*63aba447SAndreas Jaekel 201*63aba447SAndreas Jaekel static void 202*63aba447SAndreas Jaekel zev_print_znode_link(char *buf) 203*63aba447SAndreas Jaekel { 204*63aba447SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 205*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 206*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 207*63aba447SAndreas Jaekel 208*63aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s'\n", 209*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 210*63aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 211*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 212*63aba447SAndreas Jaekel ZEV_NAME(rec)); 213*63aba447SAndreas Jaekel printf("links: %d\n", rec->file.links); 214*63aba447SAndreas Jaekel } 215*63aba447SAndreas Jaekel 216*63aba447SAndreas Jaekel static void 217*63aba447SAndreas Jaekel zev_print_znode_symlink(char *buf) 218*63aba447SAndreas Jaekel { 219*63aba447SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 220*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 221*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 222*63aba447SAndreas Jaekel 223*63aba447SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 224*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 225*63aba447SAndreas Jaekel rec->parent.ino, rec->parent.gen, 226*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 227*63aba447SAndreas Jaekel ZEV_NAME(rec), 228*63aba447SAndreas Jaekel ZEV_LINK(rec)); 229*63aba447SAndreas Jaekel } 230*63aba447SAndreas Jaekel 231*63aba447SAndreas Jaekel static void 232*63aba447SAndreas Jaekel zev_print_znode_rename(char *buf) 233*63aba447SAndreas Jaekel { 234*63aba447SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 235*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 236*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 237*63aba447SAndreas Jaekel 238*63aba447SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 239*63aba447SAndreas Jaekel "srcname='%s' dstname='%s'\n", 240*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 241*63aba447SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 242*63aba447SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 243*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 244*63aba447SAndreas Jaekel ZEV_SRCNAME(rec), 245*63aba447SAndreas Jaekel ZEV_DSTNAME(rec)); 246*63aba447SAndreas Jaekel } 247*63aba447SAndreas Jaekel 248*63aba447SAndreas Jaekel static void 249*63aba447SAndreas Jaekel zev_print_znode_write(char *buf) 250*63aba447SAndreas Jaekel { 251*63aba447SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 252*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 253*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 254*63aba447SAndreas Jaekel 255*63aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 256*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 257*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen, 258*63aba447SAndreas Jaekel rec->offset, rec->length); 259*63aba447SAndreas Jaekel } 260*63aba447SAndreas Jaekel 261*63aba447SAndreas Jaekel static void 262*63aba447SAndreas Jaekel zev_print_znode_truncate(char *buf) 263*63aba447SAndreas Jaekel { 264*63aba447SAndreas Jaekel zev_print_znode_write(buf); 265*63aba447SAndreas Jaekel } 266*63aba447SAndreas Jaekel 267*63aba447SAndreas Jaekel static void 268*63aba447SAndreas Jaekel zev_print_znode_setattr(char *buf) 269*63aba447SAndreas Jaekel { 270*63aba447SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 271*63aba447SAndreas Jaekel time_t op_time = rec->op_time; 272*63aba447SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 273*63aba447SAndreas Jaekel 274*63aba447SAndreas Jaekel printf("%s %s: file=%llu.%llu\n", 275*63aba447SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 276*63aba447SAndreas Jaekel rec->file.ino, rec->file.gen); 277*63aba447SAndreas Jaekel } 278*63aba447SAndreas Jaekel 279*63aba447SAndreas Jaekel static void 280*63aba447SAndreas Jaekel zev_print_znode_acl(char *buf) 281*63aba447SAndreas Jaekel { 282*63aba447SAndreas Jaekel zev_print_znode_setattr(buf); 283*63aba447SAndreas Jaekel } 284*63aba447SAndreas Jaekel 285*63aba447SAndreas Jaekel static void 2869193e9c2SAndreas Jaekel zev_print_event(char *buf, int len) 2879193e9c2SAndreas Jaekel { 288*63aba447SAndreas Jaekel int record_len; 289*63aba447SAndreas Jaekel int op; 2909193e9c2SAndreas Jaekel 291*63aba447SAndreas Jaekel record_len = *(uint32_t *)buf; 292*63aba447SAndreas Jaekel if (record_len != len) { 293*63aba447SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 294*63aba447SAndreas Jaekel record_len, len); 2959193e9c2SAndreas Jaekel exit(1); 2969193e9c2SAndreas Jaekel } 297*63aba447SAndreas Jaekel op = *((uint32_t *)buf + 1); 2989193e9c2SAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 299*63aba447SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 3009193e9c2SAndreas Jaekel exit(1); 3019193e9c2SAndreas Jaekel } 302*63aba447SAndreas Jaekel switch (op) { 303*63aba447SAndreas Jaekel case ZEV_OP_ERROR: 304*63aba447SAndreas Jaekel zev_print_error(buf); 3059193e9c2SAndreas Jaekel break; 306*63aba447SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 307*63aba447SAndreas Jaekel zev_print_zfs_mount(buf); 3089193e9c2SAndreas Jaekel break; 309*63aba447SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 310*63aba447SAndreas Jaekel zev_print_zfs_umount(buf); 3119193e9c2SAndreas Jaekel break; 312*63aba447SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 313*63aba447SAndreas Jaekel zev_print_zvol_truncate(buf); 3149193e9c2SAndreas Jaekel break; 315*63aba447SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 316*63aba447SAndreas Jaekel zev_print_zvol_write(buf); 317*63aba447SAndreas Jaekel break; 318*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 319*63aba447SAndreas Jaekel zev_print_znode_close_after_update(buf); 320*63aba447SAndreas Jaekel break; 321*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 322*63aba447SAndreas Jaekel zev_print_znode_create(buf); 323*63aba447SAndreas Jaekel break; 324*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 325*63aba447SAndreas Jaekel zev_print_znode_mkdir(buf); 326*63aba447SAndreas Jaekel break; 327*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 328*63aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 329*63aba447SAndreas Jaekel break; 330*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 331*63aba447SAndreas Jaekel zev_print_znode_remove(buf); 332*63aba447SAndreas Jaekel break; 333*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 334*63aba447SAndreas Jaekel zev_print_znode_rmdir(buf); 335*63aba447SAndreas Jaekel break; 336*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 337*63aba447SAndreas Jaekel zev_print_znode_link(buf); 338*63aba447SAndreas Jaekel break; 339*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 340*63aba447SAndreas Jaekel zev_print_znode_symlink(buf); 341*63aba447SAndreas Jaekel break; 342*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 343*63aba447SAndreas Jaekel zev_print_znode_rename(buf); 344*63aba447SAndreas Jaekel break; 345*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 346*63aba447SAndreas Jaekel zev_print_znode_write(buf); 347*63aba447SAndreas Jaekel break; 348*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 349*63aba447SAndreas Jaekel zev_print_znode_truncate(buf); 350*63aba447SAndreas Jaekel break; 351*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 352*63aba447SAndreas Jaekel zev_print_znode_setattr(buf); 353*63aba447SAndreas Jaekel break; 354*63aba447SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 355*63aba447SAndreas Jaekel zev_print_znode_acl(buf); 3569193e9c2SAndreas Jaekel break; 3579193e9c2SAndreas Jaekel default: 358*63aba447SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 3599193e9c2SAndreas Jaekel exit(1); 3609193e9c2SAndreas Jaekel } 3619193e9c2SAndreas Jaekel } 3629193e9c2SAndreas Jaekel 3639193e9c2SAndreas Jaekel static void 3642bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 3652bb8e5e2SAndreas Jaekel { 3662bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 3672bb8e5e2SAndreas Jaekel int ret; 3689193e9c2SAndreas Jaekel char buf[4096]; 3692bb8e5e2SAndreas Jaekel while (1) { 3702bb8e5e2SAndreas Jaekel pfd[0].fd = fd; 3712bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 3722bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 3732bb8e5e2SAndreas Jaekel if (ret < 0) { 3742bb8e5e2SAndreas Jaekel perror("poll failed"); 3752bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 3762bb8e5e2SAndreas Jaekel } 3772bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 3782bb8e5e2SAndreas Jaekel continue; 3792bb8e5e2SAndreas Jaekel /* data available */ 3802bb8e5e2SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 3812bb8e5e2SAndreas Jaekel if (ret < 0) { 3822bb8e5e2SAndreas Jaekel perror("read failed"); 3832bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 3842bb8e5e2SAndreas Jaekel } 3852bb8e5e2SAndreas Jaekel if (ret == 0) 3862bb8e5e2SAndreas Jaekel continue; 3879193e9c2SAndreas Jaekel zev_print_event(buf, ret); 3882bb8e5e2SAndreas Jaekel } 3892bb8e5e2SAndreas Jaekel return; 3902bb8e5e2SAndreas Jaekel } 3912bb8e5e2SAndreas Jaekel 3922bb8e5e2SAndreas Jaekel static void 3932bb8e5e2SAndreas Jaekel usage(char *progname) 3942bb8e5e2SAndreas Jaekel { 3952bb8e5e2SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 3962bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 3972bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 3982bb8e5e2SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 399205a9bc9SAndreas Jaekel fprintf(stderr, " -t <bytes> set queue length poll throttle\n"); 4002bb8e5e2SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 4012bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 4022bb8e5e2SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 4032bb8e5e2SAndreas Jaekel ZEV_DEVICE); 4042bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 4052bb8e5e2SAndreas Jaekel } 4062bb8e5e2SAndreas Jaekel 4072bb8e5e2SAndreas Jaekel static int 4082bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 4092bb8e5e2SAndreas Jaekel { 4102bb8e5e2SAndreas Jaekel uint64_t maxqueuelen; 4112bb8e5e2SAndreas Jaekel 4122bb8e5e2SAndreas Jaekel errno = 0; 4132bb8e5e2SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 4142bb8e5e2SAndreas Jaekel if (errno) { 4152bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 4162bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4172bb8e5e2SAndreas Jaekel } 4182bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 4192bb8e5e2SAndreas Jaekel perror("setting max queue length failed"); 4202bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4212bb8e5e2SAndreas Jaekel } 4222bb8e5e2SAndreas Jaekel return (0); 4232bb8e5e2SAndreas Jaekel } 4242bb8e5e2SAndreas Jaekel 4252bb8e5e2SAndreas Jaekel static int 426205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg) 427205a9bc9SAndreas Jaekel { 428205a9bc9SAndreas Jaekel uint64_t queuelen; 429205a9bc9SAndreas Jaekel 430205a9bc9SAndreas Jaekel errno = 0; 431205a9bc9SAndreas Jaekel queuelen = strtol(optarg, (char **)NULL, 10); 432205a9bc9SAndreas Jaekel if (errno) { 433205a9bc9SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 434205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 435205a9bc9SAndreas Jaekel } 436205a9bc9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) { 437205a9bc9SAndreas Jaekel perror("setting poll wakeup queue length failed"); 438205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 439205a9bc9SAndreas Jaekel } 440205a9bc9SAndreas Jaekel return (0); 441205a9bc9SAndreas Jaekel } 442205a9bc9SAndreas Jaekel 443205a9bc9SAndreas Jaekel static int 4442bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 4452bb8e5e2SAndreas Jaekel { 4462bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 4472bb8e5e2SAndreas Jaekel int len; 4482bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 4492bb8e5e2SAndreas Jaekel len = strlen(poolname); 4502bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 4512bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 4522bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4532bb8e5e2SAndreas Jaekel } 4542bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 4552bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 4562bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 4572bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 4582bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 4592bb8e5e2SAndreas Jaekel } 4602bb8e5e2SAndreas Jaekel return (0); 4612bb8e5e2SAndreas Jaekel } 4622bb8e5e2SAndreas Jaekel 4632bb8e5e2SAndreas Jaekel int 4642bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 4652bb8e5e2SAndreas Jaekel { 4662bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 4672bb8e5e2SAndreas Jaekel } 4682bb8e5e2SAndreas Jaekel 4692bb8e5e2SAndreas Jaekel int 4702bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 4712bb8e5e2SAndreas Jaekel { 4722bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 4732bb8e5e2SAndreas Jaekel } 4742bb8e5e2SAndreas Jaekel 4752bb8e5e2SAndreas Jaekel int 4762bb8e5e2SAndreas Jaekel main(int argc, char **argv) 4772bb8e5e2SAndreas Jaekel { 4782bb8e5e2SAndreas Jaekel int fd; 4792bb8e5e2SAndreas Jaekel int c; 4802bb8e5e2SAndreas Jaekel int ops = 0; 4812bb8e5e2SAndreas Jaekel extern char *optarg; 4822bb8e5e2SAndreas Jaekel 4832bb8e5e2SAndreas Jaekel /* open device */ 4842bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 4852bb8e5e2SAndreas Jaekel if (fd < 0) { 4862bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 4872bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 4882bb8e5e2SAndreas Jaekel } 489205a9bc9SAndreas Jaekel while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) { 4902bb8e5e2SAndreas Jaekel switch(c) { 4912bb8e5e2SAndreas Jaekel case 's': 4922bb8e5e2SAndreas Jaekel ops |= OP_STATISTICS; 4932bb8e5e2SAndreas Jaekel break; 4942bb8e5e2SAndreas Jaekel case 'p': 4952bb8e5e2SAndreas Jaekel ops |= OP_POLL_EVENTS; 4962bb8e5e2SAndreas Jaekel break; 4972bb8e5e2SAndreas Jaekel case 'd': 4982bb8e5e2SAndreas Jaekel zev_device = optarg; 4992bb8e5e2SAndreas Jaekel break; 5002bb8e5e2SAndreas Jaekel case 'q': 5012bb8e5e2SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 502205a9bc9SAndreas Jaekel case 't': 503205a9bc9SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg); 5042bb8e5e2SAndreas Jaekel case 'm': 5052bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 5062bb8e5e2SAndreas Jaekel case 'M': 5072bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 5082bb8e5e2SAndreas Jaekel case 'h': 5092bb8e5e2SAndreas Jaekel case '?': 5102bb8e5e2SAndreas Jaekel default: 5112bb8e5e2SAndreas Jaekel usage(argv[0]); 5122bb8e5e2SAndreas Jaekel } 5132bb8e5e2SAndreas Jaekel } 5142bb8e5e2SAndreas Jaekel if (!ops) 5152bb8e5e2SAndreas Jaekel usage(argv[0]); 5162bb8e5e2SAndreas Jaekel if (ops & OP_STATISTICS) 5172bb8e5e2SAndreas Jaekel zev_statistics(fd); 5182bb8e5e2SAndreas Jaekel if (ops & OP_POLL_EVENTS) 5192bb8e5e2SAndreas Jaekel zev_poll_events(fd); 5202bb8e5e2SAndreas Jaekel close(fd); 5212bb8e5e2SAndreas Jaekel return EXIT_SUCCESS; 5222bb8e5e2SAndreas Jaekel } 5232bb8e5e2SAndreas Jaekel 524