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