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> 10a18c35b9SAndreas Jaekel 11a18c35b9SAndreas Jaekel #define OP_STATISTICS (1 << 0) 12a18c35b9SAndreas Jaekel #define OP_POLL_EVENTS (1 << 1) 13a18c35b9SAndreas Jaekel #define OP_MUTE_POOL (1 << 2) 14a18c35b9SAndreas Jaekel #define OP_UNMUTE_POOL (1 << 3) 15a18c35b9SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN (1 << 4) 16a18c35b9SAndreas Jaekel 17a18c35b9SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev" 18a18c35b9SAndreas Jaekel 19a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 20a18c35b9SAndreas Jaekel 21aafc540fSAndreas Jaekel static char *zev_op_name[] = { 22aafc540fSAndreas Jaekel "ZEV_OP_ERROR", 23aafc540fSAndreas Jaekel "ZEV_OP_ZFS_MOUNT", 24aafc540fSAndreas Jaekel "ZEV_OP_ZFS_UMOUNT", 25aafc540fSAndreas Jaekel "ZEV_OP_ZVOL_WRITE", 26aafc540fSAndreas Jaekel "ZEV_OP_ZVOL_TRUNCATE", 27aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 28aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_CREATE", 29aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_MKDIR", 30aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 31aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_REMOVE", 32aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_RMDIR", 33aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_LINK", 34aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_SYMLINK", 35aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_RENAME", 36aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_WRITE", 37aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_TRUNCATE", 38aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_SETATTR", 39aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_ACL", 40aafc540fSAndreas Jaekel NULL 41aafc540fSAndreas Jaekel }; 42aafc540fSAndreas Jaekel 43a18c35b9SAndreas Jaekel static void 44a18c35b9SAndreas Jaekel zev_statistics(int fd) 45a18c35b9SAndreas Jaekel { 46a18c35b9SAndreas Jaekel zev_statistics_t zs; 47a18c35b9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) { 48a18c35b9SAndreas Jaekel perror("getting statistics data failed"); 49a18c35b9SAndreas Jaekel exit (EXIT_FAILURE); 50a18c35b9SAndreas Jaekel } 51a18c35b9SAndreas Jaekel printf("ZEV module state:\n"); 52a18c35b9SAndreas Jaekel 53a18c35b9SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 54a18c35b9SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 55fec460f8SAndreas Jaekel printf(" poll wakeup throttle : %lu\n\n", 56fec460f8SAndreas Jaekel zs.zev_poll_wakeup_queue_len); 57a18c35b9SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 58a18c35b9SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 59a18c35b9SAndreas Jaekel 60a18c35b9SAndreas Jaekel printf("ZFS event statistics:\n"); 61a18c35b9SAndreas Jaekel 62a18c35b9SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 63a18c35b9SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 64a18c35b9SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 65a18c35b9SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 66a18c35b9SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 67a18c35b9SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 68a18c35b9SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 69a18c35b9SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 70a18c35b9SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 71a18c35b9SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 72a18c35b9SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 73a18c35b9SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 74a18c35b9SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 75a18c35b9SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 76a18c35b9SAndreas Jaekel zs.zev_cnt_znode_truncate); 77a18c35b9SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 78a18c35b9SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 79a18c35b9SAndreas Jaekel } 80a18c35b9SAndreas Jaekel 81a18c35b9SAndreas Jaekel static void 82*f2dd45e5SAndreas Jaekel zev_print_error(char *buf) 83*f2dd45e5SAndreas Jaekel { 84*f2dd45e5SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 85*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 86*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 87*f2dd45e5SAndreas Jaekel 88*f2dd45e5SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 89*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 90*f2dd45e5SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 91*f2dd45e5SAndreas Jaekel } 92*f2dd45e5SAndreas Jaekel 93*f2dd45e5SAndreas Jaekel static void 94*f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf) 95*f2dd45e5SAndreas Jaekel { 96*f2dd45e5SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 97*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 98*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 99*f2dd45e5SAndreas Jaekel 100*f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 101*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 102*f2dd45e5SAndreas Jaekel rec->guid, 103*f2dd45e5SAndreas Jaekel rec->remount ? "true" : "false", 104*f2dd45e5SAndreas Jaekel ZEV_DATASET(rec), 105*f2dd45e5SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 106*f2dd45e5SAndreas Jaekel } 107*f2dd45e5SAndreas Jaekel 108*f2dd45e5SAndreas Jaekel static void 109*f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf) 110*f2dd45e5SAndreas Jaekel { 111*f2dd45e5SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 112*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 113*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 114*f2dd45e5SAndreas Jaekel 115*f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu\n", 116*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 117*f2dd45e5SAndreas Jaekel rec->guid); 118*f2dd45e5SAndreas Jaekel } 119*f2dd45e5SAndreas Jaekel 120*f2dd45e5SAndreas Jaekel static void 121*f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf) 122*f2dd45e5SAndreas Jaekel { 123*f2dd45e5SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 124*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 125*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 126*f2dd45e5SAndreas Jaekel 127*f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 128*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 129*f2dd45e5SAndreas Jaekel rec->guid, 130*f2dd45e5SAndreas Jaekel rec->offset, 131*f2dd45e5SAndreas Jaekel rec->length); 132*f2dd45e5SAndreas Jaekel } 133*f2dd45e5SAndreas Jaekel 134*f2dd45e5SAndreas Jaekel static void 135*f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf) 136*f2dd45e5SAndreas Jaekel { 137*f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 138*f2dd45e5SAndreas Jaekel } 139*f2dd45e5SAndreas Jaekel 140*f2dd45e5SAndreas Jaekel static void 141*f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 142*f2dd45e5SAndreas Jaekel { 143*f2dd45e5SAndreas Jaekel zev_znode_close_after_update_t *rec = 144*f2dd45e5SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 145*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 146*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 147*f2dd45e5SAndreas Jaekel 148*f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 149*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 150*f2dd45e5SAndreas Jaekel rec->guid, 151*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen); 152*f2dd45e5SAndreas Jaekel } 153*f2dd45e5SAndreas Jaekel 154*f2dd45e5SAndreas Jaekel static void 155*f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf) 156*f2dd45e5SAndreas Jaekel { 157*f2dd45e5SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 158*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 159*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 160*f2dd45e5SAndreas Jaekel 161*f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu name='%s'\n", 162*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 163*f2dd45e5SAndreas Jaekel rec->guid, 164*f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 165*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 166*f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 167*f2dd45e5SAndreas Jaekel } 168*f2dd45e5SAndreas Jaekel 169*f2dd45e5SAndreas Jaekel static void 170*f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf) 171*f2dd45e5SAndreas Jaekel { 172*f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 173*f2dd45e5SAndreas Jaekel } 174*f2dd45e5SAndreas Jaekel 175*f2dd45e5SAndreas Jaekel static void 176*f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 177*f2dd45e5SAndreas Jaekel { 178*f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 179*f2dd45e5SAndreas Jaekel } 180*f2dd45e5SAndreas Jaekel 181*f2dd45e5SAndreas Jaekel static void 182*f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf) 183*f2dd45e5SAndreas Jaekel { 184*f2dd45e5SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 185*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 186*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 187*f2dd45e5SAndreas Jaekel 188*f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu name='%s'\n", 189*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 190*f2dd45e5SAndreas Jaekel rec->guid, 191*f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 192*f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 193*f2dd45e5SAndreas Jaekel } 194*f2dd45e5SAndreas Jaekel 195*f2dd45e5SAndreas Jaekel static void 196*f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf) 197*f2dd45e5SAndreas Jaekel { 198*f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 199*f2dd45e5SAndreas Jaekel } 200*f2dd45e5SAndreas Jaekel 201*f2dd45e5SAndreas Jaekel static void 202*f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf) 203*f2dd45e5SAndreas Jaekel { 204*f2dd45e5SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 205*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 206*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 207*f2dd45e5SAndreas Jaekel 208*f2dd45e5SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s'\n", 209*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 210*f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 211*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 212*f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 213*f2dd45e5SAndreas Jaekel printf("links: %d\n", rec->file.links); 214*f2dd45e5SAndreas Jaekel } 215*f2dd45e5SAndreas Jaekel 216*f2dd45e5SAndreas Jaekel static void 217*f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf) 218*f2dd45e5SAndreas Jaekel { 219*f2dd45e5SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 220*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 221*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 222*f2dd45e5SAndreas Jaekel 223*f2dd45e5SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 224*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 225*f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 226*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 227*f2dd45e5SAndreas Jaekel ZEV_NAME(rec), 228*f2dd45e5SAndreas Jaekel ZEV_LINK(rec)); 229*f2dd45e5SAndreas Jaekel } 230*f2dd45e5SAndreas Jaekel 231*f2dd45e5SAndreas Jaekel static void 232*f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf) 233*f2dd45e5SAndreas Jaekel { 234*f2dd45e5SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 235*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 236*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 237*f2dd45e5SAndreas Jaekel 238*f2dd45e5SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 239*f2dd45e5SAndreas Jaekel "srcname='%s' dstname='%s'\n", 240*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 241*f2dd45e5SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 242*f2dd45e5SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 243*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 244*f2dd45e5SAndreas Jaekel ZEV_SRCNAME(rec), 245*f2dd45e5SAndreas Jaekel ZEV_DSTNAME(rec)); 246*f2dd45e5SAndreas Jaekel } 247*f2dd45e5SAndreas Jaekel 248*f2dd45e5SAndreas Jaekel static void 249*f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf) 250*f2dd45e5SAndreas Jaekel { 251*f2dd45e5SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 252*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 253*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 254*f2dd45e5SAndreas Jaekel 255*f2dd45e5SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 256*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 257*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 258*f2dd45e5SAndreas Jaekel rec->offset, rec->length); 259*f2dd45e5SAndreas Jaekel } 260*f2dd45e5SAndreas Jaekel 261*f2dd45e5SAndreas Jaekel static void 262*f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf) 263*f2dd45e5SAndreas Jaekel { 264*f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 265*f2dd45e5SAndreas Jaekel } 266*f2dd45e5SAndreas Jaekel 267*f2dd45e5SAndreas Jaekel static void 268*f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf) 269*f2dd45e5SAndreas Jaekel { 270*f2dd45e5SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 271*f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 272*f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 273*f2dd45e5SAndreas Jaekel 274*f2dd45e5SAndreas Jaekel printf("%s %s: file=%llu.%llu\n", 275*f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 276*f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen); 277*f2dd45e5SAndreas Jaekel } 278*f2dd45e5SAndreas Jaekel 279*f2dd45e5SAndreas Jaekel static void 280*f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf) 281*f2dd45e5SAndreas Jaekel { 282*f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 283*f2dd45e5SAndreas Jaekel } 284*f2dd45e5SAndreas Jaekel 285*f2dd45e5SAndreas Jaekel static void 286aafc540fSAndreas Jaekel zev_print_event(char *buf, int len) 287aafc540fSAndreas Jaekel { 288*f2dd45e5SAndreas Jaekel int record_len; 289*f2dd45e5SAndreas Jaekel int op; 290aafc540fSAndreas Jaekel 291*f2dd45e5SAndreas Jaekel record_len = *(uint32_t *)buf; 292*f2dd45e5SAndreas Jaekel if (record_len != len) { 293*f2dd45e5SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 294*f2dd45e5SAndreas Jaekel record_len, len); 295aafc540fSAndreas Jaekel exit(1); 296aafc540fSAndreas Jaekel } 297*f2dd45e5SAndreas Jaekel op = *((uint32_t *)buf + 1); 298aafc540fSAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 299*f2dd45e5SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 300aafc540fSAndreas Jaekel exit(1); 301aafc540fSAndreas Jaekel } 302*f2dd45e5SAndreas Jaekel switch (op) { 303*f2dd45e5SAndreas Jaekel case ZEV_OP_ERROR: 304*f2dd45e5SAndreas Jaekel zev_print_error(buf); 305aafc540fSAndreas Jaekel break; 306*f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 307*f2dd45e5SAndreas Jaekel zev_print_zfs_mount(buf); 308aafc540fSAndreas Jaekel break; 309*f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 310*f2dd45e5SAndreas Jaekel zev_print_zfs_umount(buf); 311aafc540fSAndreas Jaekel break; 312*f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 313*f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 314aafc540fSAndreas Jaekel break; 315*f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 316*f2dd45e5SAndreas Jaekel zev_print_zvol_write(buf); 317*f2dd45e5SAndreas Jaekel break; 318*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 319*f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(buf); 320*f2dd45e5SAndreas Jaekel break; 321*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 322*f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 323*f2dd45e5SAndreas Jaekel break; 324*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 325*f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(buf); 326*f2dd45e5SAndreas Jaekel break; 327*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 328*f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 329*f2dd45e5SAndreas Jaekel break; 330*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 331*f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 332*f2dd45e5SAndreas Jaekel break; 333*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 334*f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(buf); 335*f2dd45e5SAndreas Jaekel break; 336*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 337*f2dd45e5SAndreas Jaekel zev_print_znode_link(buf); 338*f2dd45e5SAndreas Jaekel break; 339*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 340*f2dd45e5SAndreas Jaekel zev_print_znode_symlink(buf); 341*f2dd45e5SAndreas Jaekel break; 342*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 343*f2dd45e5SAndreas Jaekel zev_print_znode_rename(buf); 344*f2dd45e5SAndreas Jaekel break; 345*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 346*f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 347*f2dd45e5SAndreas Jaekel break; 348*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 349*f2dd45e5SAndreas Jaekel zev_print_znode_truncate(buf); 350*f2dd45e5SAndreas Jaekel break; 351*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 352*f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 353*f2dd45e5SAndreas Jaekel break; 354*f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 355*f2dd45e5SAndreas Jaekel zev_print_znode_acl(buf); 356aafc540fSAndreas Jaekel break; 357aafc540fSAndreas Jaekel default: 358*f2dd45e5SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 359aafc540fSAndreas Jaekel exit(1); 360aafc540fSAndreas Jaekel } 361aafc540fSAndreas Jaekel } 362aafc540fSAndreas Jaekel 363aafc540fSAndreas Jaekel static void 364a18c35b9SAndreas Jaekel zev_poll_events(int fd) 365a18c35b9SAndreas Jaekel { 366a18c35b9SAndreas Jaekel struct pollfd pfd[1]; 367a18c35b9SAndreas Jaekel int ret; 368aafc540fSAndreas Jaekel char buf[4096]; 369a18c35b9SAndreas Jaekel while (1) { 370a18c35b9SAndreas Jaekel pfd[0].fd = fd; 371a18c35b9SAndreas Jaekel pfd[0].events = POLLIN; 372a18c35b9SAndreas Jaekel ret = poll(pfd, 1, 1000); 373a18c35b9SAndreas Jaekel if (ret < 0) { 374a18c35b9SAndreas Jaekel perror("poll failed"); 375a18c35b9SAndreas Jaekel exit(EXIT_FAILURE); 376a18c35b9SAndreas Jaekel } 377a18c35b9SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 378a18c35b9SAndreas Jaekel continue; 379a18c35b9SAndreas Jaekel /* data available */ 380a18c35b9SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 381a18c35b9SAndreas Jaekel if (ret < 0) { 382a18c35b9SAndreas Jaekel perror("read failed"); 383a18c35b9SAndreas Jaekel exit(EXIT_FAILURE); 384a18c35b9SAndreas Jaekel } 385a18c35b9SAndreas Jaekel if (ret == 0) 386a18c35b9SAndreas Jaekel continue; 387aafc540fSAndreas Jaekel zev_print_event(buf, ret); 388a18c35b9SAndreas Jaekel } 389a18c35b9SAndreas Jaekel return; 390a18c35b9SAndreas Jaekel } 391a18c35b9SAndreas Jaekel 392a18c35b9SAndreas Jaekel static void 393a18c35b9SAndreas Jaekel usage(char *progname) 394a18c35b9SAndreas Jaekel { 395a18c35b9SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 396a18c35b9SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 397a18c35b9SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 398a18c35b9SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 399fec460f8SAndreas Jaekel fprintf(stderr, " -t <bytes> set queue length poll throttle\n"); 400a18c35b9SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 401a18c35b9SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 402a18c35b9SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 403a18c35b9SAndreas Jaekel ZEV_DEVICE); 404a18c35b9SAndreas Jaekel exit (EXIT_FAILURE); 405a18c35b9SAndreas Jaekel } 406a18c35b9SAndreas Jaekel 407a18c35b9SAndreas Jaekel static int 408a18c35b9SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 409a18c35b9SAndreas Jaekel { 410a18c35b9SAndreas Jaekel uint64_t maxqueuelen; 411a18c35b9SAndreas Jaekel 412a18c35b9SAndreas Jaekel errno = 0; 413a18c35b9SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 414a18c35b9SAndreas Jaekel if (errno) { 415a18c35b9SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 416a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 417a18c35b9SAndreas Jaekel } 418a18c35b9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 419a18c35b9SAndreas Jaekel perror("setting max queue length failed"); 420a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 421a18c35b9SAndreas Jaekel } 422a18c35b9SAndreas Jaekel return (0); 423a18c35b9SAndreas Jaekel } 424a18c35b9SAndreas Jaekel 425a18c35b9SAndreas Jaekel static int 426fec460f8SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg) 427fec460f8SAndreas Jaekel { 428fec460f8SAndreas Jaekel uint64_t queuelen; 429fec460f8SAndreas Jaekel 430fec460f8SAndreas Jaekel errno = 0; 431fec460f8SAndreas Jaekel queuelen = strtol(optarg, (char **)NULL, 10); 432fec460f8SAndreas Jaekel if (errno) { 433fec460f8SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 434fec460f8SAndreas Jaekel return (EXIT_FAILURE); 435fec460f8SAndreas Jaekel } 436fec460f8SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) { 437fec460f8SAndreas Jaekel perror("setting poll wakeup queue length failed"); 438fec460f8SAndreas Jaekel return (EXIT_FAILURE); 439fec460f8SAndreas Jaekel } 440fec460f8SAndreas Jaekel return (0); 441fec460f8SAndreas Jaekel } 442fec460f8SAndreas Jaekel 443fec460f8SAndreas Jaekel static int 444a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 445a18c35b9SAndreas Jaekel { 446a18c35b9SAndreas Jaekel zev_ioctl_poolarg_t pa; 447a18c35b9SAndreas Jaekel int len; 448a18c35b9SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 449a18c35b9SAndreas Jaekel len = strlen(poolname); 450a18c35b9SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 451a18c35b9SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 452a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 453a18c35b9SAndreas Jaekel } 454a18c35b9SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 455a18c35b9SAndreas Jaekel pa.zev_poolname_len = len; 456a18c35b9SAndreas Jaekel if (ioctl(fd, op, &pa)) { 457a18c35b9SAndreas Jaekel perror("muting pool data failed"); 458a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 459a18c35b9SAndreas Jaekel } 460a18c35b9SAndreas Jaekel return (0); 461a18c35b9SAndreas Jaekel } 462a18c35b9SAndreas Jaekel 463a18c35b9SAndreas Jaekel int 464a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 465a18c35b9SAndreas Jaekel { 466a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 467a18c35b9SAndreas Jaekel } 468a18c35b9SAndreas Jaekel 469a18c35b9SAndreas Jaekel int 470a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 471a18c35b9SAndreas Jaekel { 472a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 473a18c35b9SAndreas Jaekel } 474a18c35b9SAndreas Jaekel 475a18c35b9SAndreas Jaekel int 476a18c35b9SAndreas Jaekel main(int argc, char **argv) 477a18c35b9SAndreas Jaekel { 478a18c35b9SAndreas Jaekel int fd; 479a18c35b9SAndreas Jaekel int c; 480a18c35b9SAndreas Jaekel int ops = 0; 481a18c35b9SAndreas Jaekel extern char *optarg; 482a18c35b9SAndreas Jaekel 483a18c35b9SAndreas Jaekel /* open device */ 484a18c35b9SAndreas Jaekel fd = open(zev_device, O_RDONLY); 485a18c35b9SAndreas Jaekel if (fd < 0) { 486a18c35b9SAndreas Jaekel perror("opening zev device failed"); 487a18c35b9SAndreas Jaekel return EXIT_FAILURE; 488a18c35b9SAndreas Jaekel } 489fec460f8SAndreas Jaekel while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) { 490a18c35b9SAndreas Jaekel switch(c) { 491a18c35b9SAndreas Jaekel case 's': 492a18c35b9SAndreas Jaekel ops |= OP_STATISTICS; 493a18c35b9SAndreas Jaekel break; 494a18c35b9SAndreas Jaekel case 'p': 495a18c35b9SAndreas Jaekel ops |= OP_POLL_EVENTS; 496a18c35b9SAndreas Jaekel break; 497a18c35b9SAndreas Jaekel case 'd': 498a18c35b9SAndreas Jaekel zev_device = optarg; 499a18c35b9SAndreas Jaekel break; 500a18c35b9SAndreas Jaekel case 'q': 501a18c35b9SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 502fec460f8SAndreas Jaekel case 't': 503fec460f8SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg); 504a18c35b9SAndreas Jaekel case 'm': 505a18c35b9SAndreas Jaekel return zev_mute_pool(fd, optarg); 506a18c35b9SAndreas Jaekel case 'M': 507a18c35b9SAndreas Jaekel return zev_unmute_pool(fd, optarg); 508a18c35b9SAndreas Jaekel case 'h': 509a18c35b9SAndreas Jaekel case '?': 510a18c35b9SAndreas Jaekel default: 511a18c35b9SAndreas Jaekel usage(argv[0]); 512a18c35b9SAndreas Jaekel } 513a18c35b9SAndreas Jaekel } 514a18c35b9SAndreas Jaekel if (!ops) 515a18c35b9SAndreas Jaekel usage(argv[0]); 516a18c35b9SAndreas Jaekel if (ops & OP_STATISTICS) 517a18c35b9SAndreas Jaekel zev_statistics(fd); 518a18c35b9SAndreas Jaekel if (ops & OP_POLL_EVENTS) 519a18c35b9SAndreas Jaekel zev_poll_events(fd); 520a18c35b9SAndreas Jaekel close(fd); 521a18c35b9SAndreas Jaekel return EXIT_SUCCESS; 522a18c35b9SAndreas Jaekel } 523a18c35b9SAndreas Jaekel 524