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) 16add9520fSAndreas Jaekel #define OP_DEBUG_INFO (1 << 5) 17a18c35b9SAndreas Jaekel 18add9520fSAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl" 19a18c35b9SAndreas Jaekel 20a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 21a18c35b9SAndreas Jaekel 22aafc540fSAndreas Jaekel static char *zev_op_name[] = { 23aafc540fSAndreas Jaekel "ZEV_OP_ERROR", 24888fea18SAndreas Jaekel "ZEV_OP_MARK", 25aafc540fSAndreas Jaekel "ZEV_OP_ZFS_MOUNT", 26aafc540fSAndreas Jaekel "ZEV_OP_ZFS_UMOUNT", 27aafc540fSAndreas Jaekel "ZEV_OP_ZVOL_WRITE", 28aafc540fSAndreas Jaekel "ZEV_OP_ZVOL_TRUNCATE", 29aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE", 30aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_CREATE", 31aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_MKDIR", 32aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_MAKE_XATTR_DIR", 33aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_REMOVE", 34aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_RMDIR", 35aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_LINK", 36aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_SYMLINK", 37aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_RENAME", 38aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_WRITE", 39aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_TRUNCATE", 40aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_SETATTR", 41aafc540fSAndreas Jaekel "ZEV_OP_ZNODE_ACL", 42aafc540fSAndreas Jaekel NULL 43aafc540fSAndreas Jaekel }; 44aafc540fSAndreas Jaekel 45add9520fSAndreas Jaekel static int 46a18c35b9SAndreas Jaekel zev_statistics(int fd) 47a18c35b9SAndreas Jaekel { 48a18c35b9SAndreas Jaekel zev_statistics_t zs; 49add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) { 50a18c35b9SAndreas Jaekel perror("getting statistics data failed"); 51add9520fSAndreas Jaekel return (EXIT_FAILURE); 52a18c35b9SAndreas Jaekel } 53a18c35b9SAndreas Jaekel printf("ZEV module state:\n"); 54a18c35b9SAndreas Jaekel 55a18c35b9SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 56a18c35b9SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_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 60add9520fSAndreas Jaekel printf(" discarded events : %lu\n", 61add9520fSAndreas Jaekel zs.zev_cnt_discarded_events); 62add9520fSAndreas Jaekel printf(" discarded bytes : %lu\n\n", zs.zev_bytes_discarded); 63add9520fSAndreas Jaekel 64a18c35b9SAndreas Jaekel printf("ZFS event statistics:\n"); 65a18c35b9SAndreas Jaekel 66a18c35b9SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 67a18c35b9SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 68a18c35b9SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 69a18c35b9SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 70a18c35b9SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 71a18c35b9SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 72a18c35b9SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 73a18c35b9SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 74a18c35b9SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 75a18c35b9SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 76a18c35b9SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 77a18c35b9SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 78a18c35b9SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 79a18c35b9SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 80a18c35b9SAndreas Jaekel zs.zev_cnt_znode_truncate); 81a18c35b9SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 82a18c35b9SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 83add9520fSAndreas Jaekel return EXIT_SUCCESS; 84a18c35b9SAndreas Jaekel } 85a18c35b9SAndreas Jaekel 86a18c35b9SAndreas Jaekel static void 87f2dd45e5SAndreas Jaekel zev_print_error(char *buf) 88f2dd45e5SAndreas Jaekel { 89f2dd45e5SAndreas Jaekel zev_error_t *rec = (zev_error_t *)buf; 90f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 91f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 92f2dd45e5SAndreas Jaekel 93f2dd45e5SAndreas Jaekel printf("%s %s: failed_op=%s msg=%s\n", 94f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 95f2dd45e5SAndreas Jaekel zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec)); 96f2dd45e5SAndreas Jaekel } 97f2dd45e5SAndreas Jaekel 98f2dd45e5SAndreas Jaekel static void 99888fea18SAndreas Jaekel zev_print_mark(char *buf) 100888fea18SAndreas Jaekel { 101888fea18SAndreas Jaekel zev_mark_t *rec = (zev_mark_t *)buf; 102888fea18SAndreas Jaekel time_t op_time = rec->op_time; 103888fea18SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 104888fea18SAndreas Jaekel 105888fea18SAndreas Jaekel printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n", 106888fea18SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id, 107888fea18SAndreas Jaekel rec->payload_len); 108888fea18SAndreas Jaekel } 109888fea18SAndreas Jaekel 110888fea18SAndreas Jaekel static void 111f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf) 112f2dd45e5SAndreas Jaekel { 113f2dd45e5SAndreas Jaekel zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf; 114f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 115f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 116f2dd45e5SAndreas Jaekel 117f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n", 118f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 119f2dd45e5SAndreas Jaekel rec->guid, 120f2dd45e5SAndreas Jaekel rec->remount ? "true" : "false", 121f2dd45e5SAndreas Jaekel ZEV_DATASET(rec), 122f2dd45e5SAndreas Jaekel ZEV_MOUNTPOINT(rec)); 123f2dd45e5SAndreas Jaekel } 124f2dd45e5SAndreas Jaekel 125f2dd45e5SAndreas Jaekel static void 126f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf) 127f2dd45e5SAndreas Jaekel { 128f2dd45e5SAndreas Jaekel zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf; 129f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 130f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 131f2dd45e5SAndreas Jaekel 132f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu\n", 133f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 134f2dd45e5SAndreas Jaekel rec->guid); 135f2dd45e5SAndreas Jaekel } 136f2dd45e5SAndreas Jaekel 137f2dd45e5SAndreas Jaekel static void 138f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf) 139f2dd45e5SAndreas Jaekel { 140f2dd45e5SAndreas Jaekel zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf; 141f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 142f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 143f2dd45e5SAndreas Jaekel 144f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu offset=%llu length=%llu\n", 145f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 146f2dd45e5SAndreas Jaekel rec->guid, 147f2dd45e5SAndreas Jaekel rec->offset, 148f2dd45e5SAndreas Jaekel rec->length); 149f2dd45e5SAndreas Jaekel } 150f2dd45e5SAndreas Jaekel 151f2dd45e5SAndreas Jaekel static void 152f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf) 153f2dd45e5SAndreas Jaekel { 154f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 155f2dd45e5SAndreas Jaekel } 156f2dd45e5SAndreas Jaekel 157f2dd45e5SAndreas Jaekel static void 158f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf) 159f2dd45e5SAndreas Jaekel { 160f2dd45e5SAndreas Jaekel zev_znode_close_after_update_t *rec = 161f2dd45e5SAndreas Jaekel (zev_znode_close_after_update_t *)buf; 162f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 163f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 164f2dd45e5SAndreas Jaekel 165f2dd45e5SAndreas Jaekel printf("%s %s: guid=%llu file=%llu.%llu\n", 166f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 167f2dd45e5SAndreas Jaekel rec->guid, 168f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen); 169f2dd45e5SAndreas Jaekel } 170f2dd45e5SAndreas Jaekel 171f2dd45e5SAndreas Jaekel static void 172f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf) 173f2dd45e5SAndreas Jaekel { 174f2dd45e5SAndreas Jaekel zev_znode_create_t *rec = (zev_znode_create_t *)buf; 175f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 176f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 177f2dd45e5SAndreas Jaekel 17835d4e8ddSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu " 17935d4e8ddSAndreas Jaekel "file.mtime=%llu, parent.mtime=%llu, name='%s'\n", 180f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 181f2dd45e5SAndreas Jaekel rec->guid, 182f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 183f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 18435d4e8ddSAndreas Jaekel rec->file.mtime, rec->parent.mtime, 185f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 186f2dd45e5SAndreas Jaekel } 187f2dd45e5SAndreas Jaekel 188f2dd45e5SAndreas Jaekel static void 189f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf) 190f2dd45e5SAndreas Jaekel { 191f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 192f2dd45e5SAndreas Jaekel } 193f2dd45e5SAndreas Jaekel 194f2dd45e5SAndreas Jaekel static void 195f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf) 196f2dd45e5SAndreas Jaekel { 197f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 198f2dd45e5SAndreas Jaekel } 199f2dd45e5SAndreas Jaekel 200f2dd45e5SAndreas Jaekel static void 201f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf) 202f2dd45e5SAndreas Jaekel { 203f2dd45e5SAndreas Jaekel zev_znode_remove_t *rec = (zev_znode_remove_t *)buf; 204f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 205f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 206f2dd45e5SAndreas Jaekel 20797dcf88dSAndreas Jaekel printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n", 208f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 209f2dd45e5SAndreas Jaekel rec->guid, 210f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 21197dcf88dSAndreas Jaekel rec->file.mtime, 212f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 213f2dd45e5SAndreas Jaekel } 214f2dd45e5SAndreas Jaekel 215f2dd45e5SAndreas Jaekel static void 216f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf) 217f2dd45e5SAndreas Jaekel { 218f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 219f2dd45e5SAndreas Jaekel } 220f2dd45e5SAndreas Jaekel 221f2dd45e5SAndreas Jaekel static void 222f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf) 223f2dd45e5SAndreas Jaekel { 224f2dd45e5SAndreas Jaekel zev_znode_link_t *rec = (zev_znode_link_t *)buf; 225f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 226f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 227f2dd45e5SAndreas Jaekel 228a01b300aSAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu " 229a01b300aSAndreas Jaekel "file.ctime=%llu parent.ctime=%llu name='%s'\n", 230f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 231f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 232f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 233a01b300aSAndreas Jaekel rec->file.ctime, rec->parent.ctime, 234f2dd45e5SAndreas Jaekel ZEV_NAME(rec)); 235f2dd45e5SAndreas Jaekel printf("links: %d\n", rec->file.links); 236f2dd45e5SAndreas Jaekel } 237f2dd45e5SAndreas Jaekel 238f2dd45e5SAndreas Jaekel static void 239f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf) 240f2dd45e5SAndreas Jaekel { 241f2dd45e5SAndreas Jaekel zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf; 242f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 243f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 244f2dd45e5SAndreas Jaekel 245f2dd45e5SAndreas Jaekel printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n", 246f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 247f2dd45e5SAndreas Jaekel rec->parent.ino, rec->parent.gen, 248f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 249f2dd45e5SAndreas Jaekel ZEV_NAME(rec), 250f2dd45e5SAndreas Jaekel ZEV_LINK(rec)); 251f2dd45e5SAndreas Jaekel } 252f2dd45e5SAndreas Jaekel 253f2dd45e5SAndreas Jaekel static void 254f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf) 255f2dd45e5SAndreas Jaekel { 256f2dd45e5SAndreas Jaekel zev_znode_rename_t *rec = (zev_znode_rename_t *)buf; 257f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 258f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 259f2dd45e5SAndreas Jaekel 260f2dd45e5SAndreas Jaekel printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu " 26135d4e8ddSAndreas Jaekel "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, " 26235d4e8ddSAndreas Jaekel "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, " 263f2dd45e5SAndreas Jaekel "srcname='%s' dstname='%s'\n", 264f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 265f2dd45e5SAndreas Jaekel rec->srcdir.ino, rec->srcdir.gen, 266f2dd45e5SAndreas Jaekel rec->dstdir.ino, rec->dstdir.gen, 267f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 26835d4e8ddSAndreas Jaekel rec->file.mtime, rec->file.ctime, 26935d4e8ddSAndreas Jaekel rec->srcdir.mtime, rec->srcdir.ctime, 27035d4e8ddSAndreas Jaekel rec->dstdir.mtime, rec->dstdir.ctime, 271f2dd45e5SAndreas Jaekel ZEV_SRCNAME(rec), 272f2dd45e5SAndreas Jaekel ZEV_DSTNAME(rec)); 273f2dd45e5SAndreas Jaekel } 274f2dd45e5SAndreas Jaekel 275f2dd45e5SAndreas Jaekel static void 276f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf) 277f2dd45e5SAndreas Jaekel { 278f2dd45e5SAndreas Jaekel zev_znode_write_t *rec = (zev_znode_write_t *)buf; 279f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 280f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 281f2dd45e5SAndreas Jaekel 282f2dd45e5SAndreas Jaekel printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n", 283f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 284f2dd45e5SAndreas Jaekel rec->file.ino, rec->file.gen, 285f2dd45e5SAndreas Jaekel rec->offset, rec->length); 286f2dd45e5SAndreas Jaekel } 287f2dd45e5SAndreas Jaekel 288f2dd45e5SAndreas Jaekel static void 289f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf) 290f2dd45e5SAndreas Jaekel { 291f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 292f2dd45e5SAndreas Jaekel } 293f2dd45e5SAndreas Jaekel 294f2dd45e5SAndreas Jaekel static void 295f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf) 296f2dd45e5SAndreas Jaekel { 297f2dd45e5SAndreas Jaekel zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf; 298f2dd45e5SAndreas Jaekel time_t op_time = rec->op_time; 299f2dd45e5SAndreas Jaekel char *ct = ctime(&op_time); ct[24] = '\0'; 300f2dd45e5SAndreas Jaekel 30135d4e8ddSAndreas Jaekel printf("%s %s: file=%llu.%llu mtime=%llu\n", 302f2dd45e5SAndreas Jaekel ct, zev_op_name[rec->op - ZEV_OP_MIN], 30335d4e8ddSAndreas Jaekel rec->file.ino, rec->file.gen, rec->file.mtime); 304f2dd45e5SAndreas Jaekel } 305f2dd45e5SAndreas Jaekel 306f2dd45e5SAndreas Jaekel static void 307f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf) 308f2dd45e5SAndreas Jaekel { 309f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 310f2dd45e5SAndreas Jaekel } 311f2dd45e5SAndreas Jaekel 312f2dd45e5SAndreas Jaekel static void 313aafc540fSAndreas Jaekel zev_print_event(char *buf, int len) 314aafc540fSAndreas Jaekel { 315f2dd45e5SAndreas Jaekel int record_len; 316f2dd45e5SAndreas Jaekel int op; 317aafc540fSAndreas Jaekel 318f2dd45e5SAndreas Jaekel record_len = *(uint32_t *)buf; 319f2dd45e5SAndreas Jaekel if (record_len != len) { 320f2dd45e5SAndreas Jaekel fprintf(stderr, "record length mismatch: got %d, expected %d\n", 321f2dd45e5SAndreas Jaekel record_len, len); 322aafc540fSAndreas Jaekel exit(1); 323aafc540fSAndreas Jaekel } 324f2dd45e5SAndreas Jaekel op = *((uint32_t *)buf + 1); 325aafc540fSAndreas Jaekel if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) { 326f2dd45e5SAndreas Jaekel fprintf(stderr, "unknown op code: %d\n", op); 327aafc540fSAndreas Jaekel exit(1); 328aafc540fSAndreas Jaekel } 329f2dd45e5SAndreas Jaekel switch (op) { 330f2dd45e5SAndreas Jaekel case ZEV_OP_ERROR: 331f2dd45e5SAndreas Jaekel zev_print_error(buf); 332aafc540fSAndreas Jaekel break; 333888fea18SAndreas Jaekel case ZEV_OP_MARK: 334888fea18SAndreas Jaekel zev_print_mark(buf); 335888fea18SAndreas Jaekel break; 336f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_MOUNT: 337f2dd45e5SAndreas Jaekel zev_print_zfs_mount(buf); 338aafc540fSAndreas Jaekel break; 339f2dd45e5SAndreas Jaekel case ZEV_OP_ZFS_UMOUNT: 340f2dd45e5SAndreas Jaekel zev_print_zfs_umount(buf); 341aafc540fSAndreas Jaekel break; 342f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_TRUNCATE: 343f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(buf); 344aafc540fSAndreas Jaekel break; 345f2dd45e5SAndreas Jaekel case ZEV_OP_ZVOL_WRITE: 346f2dd45e5SAndreas Jaekel zev_print_zvol_write(buf); 347f2dd45e5SAndreas Jaekel break; 348f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE: 349f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(buf); 350f2dd45e5SAndreas Jaekel break; 351f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_CREATE: 352f2dd45e5SAndreas Jaekel zev_print_znode_create(buf); 353f2dd45e5SAndreas Jaekel break; 354f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MKDIR: 355f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(buf); 356f2dd45e5SAndreas Jaekel break; 357f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_MAKE_XATTR_DIR: 358f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(buf); 359f2dd45e5SAndreas Jaekel break; 360f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_REMOVE: 361f2dd45e5SAndreas Jaekel zev_print_znode_remove(buf); 362f2dd45e5SAndreas Jaekel break; 363f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RMDIR: 364f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(buf); 365f2dd45e5SAndreas Jaekel break; 366f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_LINK: 367f2dd45e5SAndreas Jaekel zev_print_znode_link(buf); 368f2dd45e5SAndreas Jaekel break; 369f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SYMLINK: 370f2dd45e5SAndreas Jaekel zev_print_znode_symlink(buf); 371f2dd45e5SAndreas Jaekel break; 372f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_RENAME: 373f2dd45e5SAndreas Jaekel zev_print_znode_rename(buf); 374f2dd45e5SAndreas Jaekel break; 375f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_WRITE: 376f2dd45e5SAndreas Jaekel zev_print_znode_write(buf); 377f2dd45e5SAndreas Jaekel break; 378f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_TRUNCATE: 379f2dd45e5SAndreas Jaekel zev_print_znode_truncate(buf); 380f2dd45e5SAndreas Jaekel break; 381f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_SETATTR: 382f2dd45e5SAndreas Jaekel zev_print_znode_setattr(buf); 383f2dd45e5SAndreas Jaekel break; 384f2dd45e5SAndreas Jaekel case ZEV_OP_ZNODE_ACL: 385f2dd45e5SAndreas Jaekel zev_print_znode_acl(buf); 386aafc540fSAndreas Jaekel break; 387aafc540fSAndreas Jaekel default: 388f2dd45e5SAndreas Jaekel fprintf(stderr, "unhandled op code: %d\n", op); 389aafc540fSAndreas Jaekel exit(1); 390aafc540fSAndreas Jaekel } 391aafc540fSAndreas Jaekel } 392aafc540fSAndreas Jaekel 393add9520fSAndreas Jaekel static int 394*6a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue) 395a18c35b9SAndreas Jaekel { 396a18c35b9SAndreas Jaekel struct pollfd pfd[1]; 397a18c35b9SAndreas Jaekel int ret; 398aafc540fSAndreas Jaekel char buf[4096]; 399d979f56cSAndreas Jaekel zev_event_t *ev; 400d979f56cSAndreas Jaekel int off = 0; 401add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 402add9520fSAndreas Jaekel int q_fd; 403add9520fSAndreas Jaekel 404*6a6a51eeSAndreas Jaekel if (create_tmp_queue) { 405add9520fSAndreas Jaekel aq.zev_max_queue_len = 0; 406add9520fSAndreas Jaekel aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 407add9520fSAndreas Jaekel snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN, 408add9520fSAndreas Jaekel "zevadm.%ld.%ld", time(NULL), getpid()); 409add9520fSAndreas Jaekel aq.zev_namelen = strlen(aq.zev_name); 410add9520fSAndreas Jaekel 411add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 412add9520fSAndreas Jaekel perror("adding temporary queue failed"); 413add9520fSAndreas Jaekel return (EXIT_FAILURE); 414add9520fSAndreas Jaekel } 415add9520fSAndreas Jaekel 416*6a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 417*6a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", aq.zev_name); 418add9520fSAndreas Jaekel q_fd = open(buf, O_RDONLY); 419add9520fSAndreas Jaekel if (q_fd < 0) { 420add9520fSAndreas Jaekel perror("opening queue device failed"); 421add9520fSAndreas Jaekel return (EXIT_FAILURE); 422add9520fSAndreas Jaekel } 423*6a6a51eeSAndreas Jaekel } else { 424*6a6a51eeSAndreas Jaekel q_fd = fd; 425*6a6a51eeSAndreas Jaekel } 426add9520fSAndreas Jaekel 427a18c35b9SAndreas Jaekel while (1) { 428add9520fSAndreas Jaekel pfd[0].fd = q_fd; 429a18c35b9SAndreas Jaekel pfd[0].events = POLLIN; 430a18c35b9SAndreas Jaekel ret = poll(pfd, 1, 1000); 431a18c35b9SAndreas Jaekel if (ret < 0) { 432a18c35b9SAndreas Jaekel perror("poll failed"); 433*6a6a51eeSAndreas Jaekel close(q_fd); 434add9520fSAndreas Jaekel return(EXIT_FAILURE); 435a18c35b9SAndreas Jaekel } 436a18c35b9SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 437a18c35b9SAndreas Jaekel continue; 438a18c35b9SAndreas Jaekel /* data available */ 439add9520fSAndreas Jaekel ret = read(q_fd, buf, sizeof(buf)); 440a18c35b9SAndreas Jaekel if (ret < 0) { 441a18c35b9SAndreas Jaekel perror("read failed"); 442*6a6a51eeSAndreas Jaekel close(q_fd); 443add9520fSAndreas Jaekel return(EXIT_FAILURE); 444a18c35b9SAndreas Jaekel } 445a18c35b9SAndreas Jaekel if (ret == 0) 446a18c35b9SAndreas Jaekel continue; 447d979f56cSAndreas Jaekel while (ret > off) { 448d979f56cSAndreas Jaekel ev = (zev_event_t *)(buf + off); 449d979f56cSAndreas Jaekel zev_print_event(buf + off, ev->header.record_len); 450d979f56cSAndreas Jaekel off += ev->header.record_len; 451d979f56cSAndreas Jaekel } 452149d0affSAndreas Jaekel off = 0; 453a18c35b9SAndreas Jaekel } 454*6a6a51eeSAndreas Jaekel if (create_tmp_queue) 455add9520fSAndreas Jaekel close(q_fd); 456add9520fSAndreas Jaekel return EXIT_SUCCESS; 457a18c35b9SAndreas Jaekel } 458a18c35b9SAndreas Jaekel 459a18c35b9SAndreas Jaekel static void 460a18c35b9SAndreas Jaekel usage(char *progname) 461a18c35b9SAndreas Jaekel { 462add9520fSAndreas Jaekel fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname); 463add9520fSAndreas Jaekel fprintf(stderr, "\n"); 464add9520fSAndreas Jaekel fprintf(stderr, " Status information:\n"); 465a18c35b9SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 466a18c35b9SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 467add9520fSAndreas Jaekel fprintf(stderr, " -D print zev module debug " 468add9520fSAndreas Jaekel "information\n"); 469add9520fSAndreas Jaekel fprintf(stderr, "\n"); 470add9520fSAndreas Jaekel fprintf(stderr, " Tune zev module settings:\n"); 471add9520fSAndreas Jaekel fprintf(stderr, " -Q <bytes> set maximum event queue " 472add9520fSAndreas Jaekel "length\n"); 473add9520fSAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for " 474add9520fSAndreas Jaekel "this pool\n"); 475a18c35b9SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 476add9520fSAndreas Jaekel fprintf(stderr, "\n"); 477add9520fSAndreas Jaekel fprintf(stderr, " Queue management:\n"); 478add9520fSAndreas Jaekel fprintf(stderr, " -l list queues\n"); 479*6a6a51eeSAndreas Jaekel fprintf(stderr, " -a <name> add non-blocking queue\n"); 480*6a6a51eeSAndreas Jaekel fprintf(stderr, " -A <name> add blocking queue\n"); 481add9520fSAndreas Jaekel fprintf(stderr, " -r <name> remove queue\n"); 482add9520fSAndreas Jaekel fprintf(stderr, " -b <name> make queue non-blocking " 483add9520fSAndreas Jaekel "(default)\n"); 484add9520fSAndreas Jaekel fprintf(stderr, " -B <name> make queue block when full\n"); 485add9520fSAndreas Jaekel fprintf(stderr, " -P <name> display queue properties\n"); 486*6a6a51eeSAndreas Jaekel fprintf(stderr, " -L <name> <bytes> set maximum event queue " 487add9520fSAndreas Jaekel "length\n"); 488add9520fSAndreas Jaekel fprintf(stderr, " -t <name> <bytes> set queue length poll " 489add9520fSAndreas Jaekel "throttle\n"); 490add9520fSAndreas Jaekel fprintf(stderr, "\n"); 491add9520fSAndreas Jaekel fprintf(stderr, " Other options:\n"); 492add9520fSAndreas Jaekel fprintf(stderr, " -d <dev> non-default device file. " 493add9520fSAndreas Jaekel "('%s')\n", ZEV_DEVICE); 494*6a6a51eeSAndreas Jaekel fprintf(stderr, " -q <name> use device file for this " 495*6a6a51eeSAndreas Jaekel "queue name\n"); 496888fea18SAndreas Jaekel fprintf(stderr, " -k <guid>:<payload> queue mark event\n"); 497a18c35b9SAndreas Jaekel exit (EXIT_FAILURE); 498a18c35b9SAndreas Jaekel } 499a18c35b9SAndreas Jaekel 500a18c35b9SAndreas Jaekel static int 501*6a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking) 502a18c35b9SAndreas Jaekel { 503add9520fSAndreas Jaekel zev_ioctl_add_queue_t aq; 504add9520fSAndreas Jaekel int namelen; 505a18c35b9SAndreas Jaekel 506add9520fSAndreas Jaekel namelen = strlen(arg); 507add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 508add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 509a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 510a18c35b9SAndreas Jaekel } 511add9520fSAndreas Jaekel 512add9520fSAndreas Jaekel aq.zev_namelen = namelen; 513add9520fSAndreas Jaekel strcpy(aq.zev_name, arg); 514*6a6a51eeSAndreas Jaekel aq.zev_flags = ZEV_FL_PERSISTENT; 515*6a6a51eeSAndreas Jaekel if (blocking) { 516*6a6a51eeSAndreas Jaekel aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 517*6a6a51eeSAndreas Jaekel aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN; 518*6a6a51eeSAndreas Jaekel } else { 519add9520fSAndreas Jaekel aq.zev_max_queue_len = (1024 * 1024); 520*6a6a51eeSAndreas Jaekel } 521add9520fSAndreas Jaekel 522add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) { 523add9520fSAndreas Jaekel perror("adding queue failed"); 524a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 525a18c35b9SAndreas Jaekel } 526a18c35b9SAndreas Jaekel return (0); 527a18c35b9SAndreas Jaekel } 528a18c35b9SAndreas Jaekel 529a18c35b9SAndreas Jaekel static int 530add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg) 531fec460f8SAndreas Jaekel { 532add9520fSAndreas Jaekel zev_ioctl_remove_queue_t aq; 533add9520fSAndreas Jaekel int namelen; 534fec460f8SAndreas Jaekel 535add9520fSAndreas Jaekel namelen = strlen(arg); 536add9520fSAndreas Jaekel if (namelen > ZEV_MAX_QUEUE_NAME_LEN) { 537add9520fSAndreas Jaekel fprintf(stderr, "queue name too long: %s\n", arg); 538fec460f8SAndreas Jaekel return (EXIT_FAILURE); 539fec460f8SAndreas Jaekel } 540add9520fSAndreas Jaekel 541*6a6a51eeSAndreas Jaekel aq.zev_queue_name.zev_namelen = namelen; 542*6a6a51eeSAndreas Jaekel strcpy(aq.zev_queue_name.zev_name, arg); 543add9520fSAndreas Jaekel 544add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) { 545add9520fSAndreas Jaekel perror("removing queue failed"); 546add9520fSAndreas Jaekel return (EXIT_FAILURE); 547add9520fSAndreas Jaekel } 548add9520fSAndreas Jaekel return (0); 549add9520fSAndreas Jaekel } 550add9520fSAndreas Jaekel 551add9520fSAndreas Jaekel static int 552add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg) 553add9520fSAndreas Jaekel { 554add9520fSAndreas Jaekel uint64_t maxqueuelen; 555add9520fSAndreas Jaekel 556add9520fSAndreas Jaekel errno = 0; 557add9520fSAndreas Jaekel maxqueuelen = strtol(arg, (char **)NULL, 10); 558add9520fSAndreas Jaekel if (errno) { 559add9520fSAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", arg); 560add9520fSAndreas Jaekel return (EXIT_FAILURE); 561add9520fSAndreas Jaekel } 562add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 563add9520fSAndreas Jaekel perror("setting max queue length failed"); 564fec460f8SAndreas Jaekel return (EXIT_FAILURE); 565fec460f8SAndreas Jaekel } 566fec460f8SAndreas Jaekel return (0); 567fec460f8SAndreas Jaekel } 568fec460f8SAndreas Jaekel 569fec460f8SAndreas Jaekel static int 570a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 571a18c35b9SAndreas Jaekel { 572a18c35b9SAndreas Jaekel zev_ioctl_poolarg_t pa; 573a18c35b9SAndreas Jaekel int len; 574a18c35b9SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 575a18c35b9SAndreas Jaekel len = strlen(poolname); 576a18c35b9SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 577a18c35b9SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 578a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 579a18c35b9SAndreas Jaekel } 580a18c35b9SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 581a18c35b9SAndreas Jaekel pa.zev_poolname_len = len; 582a18c35b9SAndreas Jaekel if (ioctl(fd, op, &pa)) { 583a18c35b9SAndreas Jaekel perror("muting pool data failed"); 584a18c35b9SAndreas Jaekel return (EXIT_FAILURE); 585a18c35b9SAndreas Jaekel } 586a18c35b9SAndreas Jaekel return (0); 587a18c35b9SAndreas Jaekel } 588a18c35b9SAndreas Jaekel 589a18c35b9SAndreas Jaekel int 590a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 591a18c35b9SAndreas Jaekel { 592a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 593a18c35b9SAndreas Jaekel } 594a18c35b9SAndreas Jaekel 595a18c35b9SAndreas Jaekel int 596a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 597a18c35b9SAndreas Jaekel { 598a18c35b9SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 599a18c35b9SAndreas Jaekel } 600a18c35b9SAndreas Jaekel 601888fea18SAndreas Jaekel static int 602add9520fSAndreas Jaekel zev_debug_info(int fd) 603add9520fSAndreas Jaekel { 604add9520fSAndreas Jaekel zev_ioctl_debug_info_t di; 605add9520fSAndreas Jaekel 606add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) { 607add9520fSAndreas Jaekel perror("getting zev debug info failed"); 608add9520fSAndreas Jaekel return (EXIT_FAILURE); 609add9520fSAndreas Jaekel } 610add9520fSAndreas Jaekel 611add9520fSAndreas Jaekel printf("memory allocated: %llu bytes\n", di.zev_memory_allocated); 612add9520fSAndreas Jaekel return 0; 613add9520fSAndreas Jaekel } 614add9520fSAndreas Jaekel 615add9520fSAndreas Jaekel static int 616888fea18SAndreas Jaekel zev_mark(int fd, char *arg) 617888fea18SAndreas Jaekel { 618888fea18SAndreas Jaekel zev_ioctl_mark_t *mark; 619888fea18SAndreas Jaekel uint64_t guid; 620888fea18SAndreas Jaekel int len; 621888fea18SAndreas Jaekel char *p; 622888fea18SAndreas Jaekel 623888fea18SAndreas Jaekel p = strchr(arg, ':'); 624888fea18SAndreas Jaekel if (!p) { 625888fea18SAndreas Jaekel fprintf(stderr, "expected value is <guid>:<payload>, " 626888fea18SAndreas Jaekel "e.g. '123:hello'\n"); 627888fea18SAndreas Jaekel exit (EXIT_FAILURE); 628888fea18SAndreas Jaekel } 629888fea18SAndreas Jaekel *p = '\n'; 630888fea18SAndreas Jaekel p++; 631888fea18SAndreas Jaekel 632888fea18SAndreas Jaekel errno = 0; 633add9520fSAndreas Jaekel guid = strtoll(arg, (char **)NULL, 10); 634888fea18SAndreas Jaekel if (errno) { 635888fea18SAndreas Jaekel fprintf(stderr, "guid must be a number.\n"); 636888fea18SAndreas Jaekel exit (EXIT_FAILURE); 637888fea18SAndreas Jaekel } 638888fea18SAndreas Jaekel 639888fea18SAndreas Jaekel len = strlen(p); 640888fea18SAndreas Jaekel 641888fea18SAndreas Jaekel mark = malloc(sizeof(*mark) + len + 1); 642888fea18SAndreas Jaekel if (!mark) { 643888fea18SAndreas Jaekel fprintf(stderr, "can't allocate mark structure: %s\n", 644888fea18SAndreas Jaekel strerror(errno)); 645888fea18SAndreas Jaekel exit (EXIT_FAILURE); 646888fea18SAndreas Jaekel } 647888fea18SAndreas Jaekel mark->zev_guid = guid; 648888fea18SAndreas Jaekel mark->zev_mark_id = 0; 649888fea18SAndreas Jaekel mark->zev_payload_len = len; 650888fea18SAndreas Jaekel strcpy(ZEV_PAYLOAD(mark), p); 651888fea18SAndreas Jaekel 652888fea18SAndreas Jaekel if (ioctl(fd, ZEV_IOC_MARK, mark)) { 653888fea18SAndreas Jaekel perror("queueing mark failed"); 654888fea18SAndreas Jaekel return (EXIT_FAILURE); 655888fea18SAndreas Jaekel } 656888fea18SAndreas Jaekel 657888fea18SAndreas Jaekel printf("mark id: %lu\n", mark->zev_mark_id); 658888fea18SAndreas Jaekel return (0); 659888fea18SAndreas Jaekel } 660888fea18SAndreas Jaekel 661add9520fSAndreas Jaekel static int 662add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block) 663add9520fSAndreas Jaekel { 664add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 665add9520fSAndreas Jaekel 666*6a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 667*6a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 668add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 669add9520fSAndreas Jaekel return EXIT_FAILURE; 670add9520fSAndreas Jaekel } 671*6a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 672add9520fSAndreas Jaekel 673add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 674add9520fSAndreas Jaekel perror("getting queue properties failed"); 675add9520fSAndreas Jaekel return (EXIT_FAILURE); 676add9520fSAndreas Jaekel } 677add9520fSAndreas Jaekel if (block) { 678add9520fSAndreas Jaekel gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 679add9520fSAndreas Jaekel } else { 680add9520fSAndreas Jaekel gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL; 681add9520fSAndreas Jaekel } 682add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 683add9520fSAndreas Jaekel perror("setting queue properties failed"); 684add9520fSAndreas Jaekel return (EXIT_FAILURE); 685add9520fSAndreas Jaekel } 686add9520fSAndreas Jaekel return (0); 687add9520fSAndreas Jaekel } 688add9520fSAndreas Jaekel 689add9520fSAndreas Jaekel static int 690add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len) 691add9520fSAndreas Jaekel { 692add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 693add9520fSAndreas Jaekel 694add9520fSAndreas Jaekel if (!len) { 695add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter missing.\n"); 696add9520fSAndreas Jaekel return EXIT_FAILURE; 697add9520fSAndreas Jaekel } 698add9520fSAndreas Jaekel 699*6a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 700*6a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 701add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 702add9520fSAndreas Jaekel return EXIT_FAILURE; 703add9520fSAndreas Jaekel } 704*6a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 705add9520fSAndreas Jaekel 706add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 707add9520fSAndreas Jaekel perror("getting queue properties failed"); 708add9520fSAndreas Jaekel return (EXIT_FAILURE); 709add9520fSAndreas Jaekel } 710add9520fSAndreas Jaekel gqp.zev_max_queue_len = atol(len); 711add9520fSAndreas Jaekel if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) { 712add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter garbled.\n"); 713add9520fSAndreas Jaekel return (EXIT_FAILURE); 714add9520fSAndreas Jaekel } 715add9520fSAndreas Jaekel if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) { 716add9520fSAndreas Jaekel fprintf(stderr, "queue size parameter out of bounds.\n"); 717add9520fSAndreas Jaekel return (EXIT_FAILURE); 718add9520fSAndreas Jaekel } 719add9520fSAndreas Jaekel 720add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 721add9520fSAndreas Jaekel perror("setting queue properties failed"); 722add9520fSAndreas Jaekel return (EXIT_FAILURE); 723add9520fSAndreas Jaekel } 724add9520fSAndreas Jaekel return (0); 725add9520fSAndreas Jaekel } 726add9520fSAndreas Jaekel 727add9520fSAndreas Jaekel static int 728add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len) 729add9520fSAndreas Jaekel { 730add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 731add9520fSAndreas Jaekel 732add9520fSAndreas Jaekel if (!len) { 733add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter missing.\n"); 734add9520fSAndreas Jaekel return EXIT_FAILURE; 735add9520fSAndreas Jaekel } 736add9520fSAndreas Jaekel 737*6a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 738*6a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 739add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 740add9520fSAndreas Jaekel return EXIT_FAILURE; 741add9520fSAndreas Jaekel } 742*6a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 743add9520fSAndreas Jaekel 744add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 745add9520fSAndreas Jaekel perror("getting queue properties failed"); 746add9520fSAndreas Jaekel return (EXIT_FAILURE); 747add9520fSAndreas Jaekel } 748add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold = atol(len); 749add9520fSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) { 750add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter garbled.\n"); 751add9520fSAndreas Jaekel return (EXIT_FAILURE); 752add9520fSAndreas Jaekel } 753*6a6a51eeSAndreas Jaekel if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) { 754add9520fSAndreas Jaekel fprintf(stderr, "poll throttle parameter out of bounds.\n"); 755add9520fSAndreas Jaekel return (EXIT_FAILURE); 756add9520fSAndreas Jaekel } 757add9520fSAndreas Jaekel 758add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) { 759add9520fSAndreas Jaekel perror("setting queue properties failed"); 760add9520fSAndreas Jaekel return (EXIT_FAILURE); 761add9520fSAndreas Jaekel } 762add9520fSAndreas Jaekel return (0); 763add9520fSAndreas Jaekel } 764add9520fSAndreas Jaekel 765add9520fSAndreas Jaekel static int 766add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg) 767add9520fSAndreas Jaekel { 768add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 769add9520fSAndreas Jaekel 770*6a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = strlen(arg); 771*6a6a51eeSAndreas Jaekel if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) { 772add9520fSAndreas Jaekel fprintf(stderr, "queue name too long.\n"); 773add9520fSAndreas Jaekel return EXIT_FAILURE; 774add9520fSAndreas Jaekel } 775*6a6a51eeSAndreas Jaekel strcpy(gqp.zev_queue_name.zev_name, arg); 776add9520fSAndreas Jaekel 777add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 778add9520fSAndreas Jaekel perror("getting queue properties failed"); 779add9520fSAndreas Jaekel return (EXIT_FAILURE); 780add9520fSAndreas Jaekel } 781add9520fSAndreas Jaekel 782add9520fSAndreas Jaekel printf("queue : %s\n", arg); 783add9520fSAndreas Jaekel printf("max size : %" PRIu64 "\n", gqp.zev_max_queue_len); 784add9520fSAndreas Jaekel printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold); 785add9520fSAndreas Jaekel printf("persistent : %s\n", 786add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no"); 787add9520fSAndreas Jaekel printf("blocking : %s\n", 788add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no"); 789add9520fSAndreas Jaekel 790add9520fSAndreas Jaekel return (0); 791add9520fSAndreas Jaekel } 792add9520fSAndreas Jaekel 793add9520fSAndreas Jaekel static int 794add9520fSAndreas Jaekel zev_list_queues(int fd) 795add9520fSAndreas Jaekel { 796add9520fSAndreas Jaekel zev_ioctl_get_queue_properties_t gqp; 797add9520fSAndreas Jaekel zev_ioctl_get_queue_list_t gql; 798add9520fSAndreas Jaekel zev_ioctl_get_queue_statistics_t gs; 799add9520fSAndreas Jaekel uint64_t i; 800add9520fSAndreas Jaekel char name[ZEV_MAX_QUEUE_NAME_LEN+1]; 801add9520fSAndreas Jaekel 802add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) { 803add9520fSAndreas Jaekel perror("getting queue list failed"); 804add9520fSAndreas Jaekel return (EXIT_FAILURE); 805add9520fSAndreas Jaekel } 806add9520fSAndreas Jaekel 807add9520fSAndreas Jaekel printf("Name Size " 808add9520fSAndreas Jaekel "Max Size Wakeup Per Block\n"); 809add9520fSAndreas Jaekel 810add9520fSAndreas Jaekel for (i=0; i<gql.zev_n_queues; i++) { 811add9520fSAndreas Jaekel strncpy(name, gql.zev_queue_name[i].zev_name, 812add9520fSAndreas Jaekel ZEV_MAX_QUEUE_NAME_LEN); 813add9520fSAndreas Jaekel name[gql.zev_queue_name[i].zev_namelen] = '\0'; 814add9520fSAndreas Jaekel 815*6a6a51eeSAndreas Jaekel memcpy(gqp.zev_queue_name.zev_name, 816*6a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 817*6a6a51eeSAndreas Jaekel gqp.zev_queue_name.zev_namelen = 818*6a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 819add9520fSAndreas Jaekel 820add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) { 821add9520fSAndreas Jaekel if (errno == ENOENT) 822add9520fSAndreas Jaekel continue; 823add9520fSAndreas Jaekel perror("getting queue properties failed"); 824add9520fSAndreas Jaekel return (EXIT_FAILURE); 825add9520fSAndreas Jaekel } 826add9520fSAndreas Jaekel 827*6a6a51eeSAndreas Jaekel memcpy(gs.zev_queue_name.zev_name, 828*6a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN); 829*6a6a51eeSAndreas Jaekel gs.zev_queue_name.zev_namelen = 830*6a6a51eeSAndreas Jaekel gql.zev_queue_name[i].zev_namelen; 831add9520fSAndreas Jaekel 832add9520fSAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) { 833add9520fSAndreas Jaekel if (errno == ENOENT) 834add9520fSAndreas Jaekel continue; 835add9520fSAndreas Jaekel perror("getting statistics data failed"); 836add9520fSAndreas Jaekel return (EXIT_FAILURE); 837add9520fSAndreas Jaekel } 838add9520fSAndreas Jaekel 839add9520fSAndreas Jaekel printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64 840add9520fSAndreas Jaekel " %-3s %-3s\n", 841add9520fSAndreas Jaekel name, 842add9520fSAndreas Jaekel gs.zev_statistics.zev_queue_len, 843add9520fSAndreas Jaekel gqp.zev_max_queue_len, 844add9520fSAndreas Jaekel gqp.zev_poll_wakeup_threshold, 845add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no", 846add9520fSAndreas Jaekel gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? 847add9520fSAndreas Jaekel "yes" : "no"); 848add9520fSAndreas Jaekel } 849add9520fSAndreas Jaekel 850add9520fSAndreas Jaekel return (0); 851add9520fSAndreas Jaekel } 852add9520fSAndreas Jaekel 853a18c35b9SAndreas Jaekel int 854a18c35b9SAndreas Jaekel main(int argc, char **argv) 855a18c35b9SAndreas Jaekel { 856a18c35b9SAndreas Jaekel int fd; 857a18c35b9SAndreas Jaekel int c; 858a18c35b9SAndreas Jaekel extern char *optarg; 859*6a6a51eeSAndreas Jaekel int create_tmp_queue = 1; 860*6a6a51eeSAndreas Jaekel char buf[MAXPATHLEN]; 861a18c35b9SAndreas Jaekel 862a18c35b9SAndreas Jaekel /* open device */ 863a18c35b9SAndreas Jaekel fd = open(zev_device, O_RDONLY); 864a18c35b9SAndreas Jaekel if (fd < 0) { 865a18c35b9SAndreas Jaekel perror("opening zev device failed"); 866a18c35b9SAndreas Jaekel return EXIT_FAILURE; 867a18c35b9SAndreas Jaekel } 868*6a6a51eeSAndreas Jaekel while ((c = getopt(argc, argv, 869*6a6a51eeSAndreas Jaekel "spd:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){ 870a18c35b9SAndreas Jaekel switch(c) { 871a18c35b9SAndreas Jaekel case 's': 872add9520fSAndreas Jaekel return zev_statistics(fd); 873a18c35b9SAndreas Jaekel case 'p': 874*6a6a51eeSAndreas Jaekel return zev_poll_events(fd, create_tmp_queue); 875add9520fSAndreas Jaekel case 'D': 876add9520fSAndreas Jaekel return zev_debug_info(fd); 877a18c35b9SAndreas Jaekel case 'd': 878add9520fSAndreas Jaekel close(fd); 879a18c35b9SAndreas Jaekel zev_device = optarg; 880add9520fSAndreas Jaekel fd = open(zev_device, O_RDONLY); 881add9520fSAndreas Jaekel if (fd < 0) { 882add9520fSAndreas Jaekel perror("opening zev device failed"); 883add9520fSAndreas Jaekel return EXIT_FAILURE; 884add9520fSAndreas Jaekel } 885*6a6a51eeSAndreas Jaekel create_tmp_queue = 0; 886*6a6a51eeSAndreas Jaekel break; 887*6a6a51eeSAndreas Jaekel case 'q': 888*6a6a51eeSAndreas Jaekel snprintf(buf, sizeof(buf), 889*6a6a51eeSAndreas Jaekel "/devices/pseudo/zev@0:%s", optarg); 890*6a6a51eeSAndreas Jaekel close(fd); 891*6a6a51eeSAndreas Jaekel zev_device = buf; 892*6a6a51eeSAndreas Jaekel fd = open(zev_device, O_RDONLY); 893*6a6a51eeSAndreas Jaekel if (fd < 0) { 894*6a6a51eeSAndreas Jaekel perror("opening zev device failed"); 895*6a6a51eeSAndreas Jaekel return EXIT_FAILURE; 896*6a6a51eeSAndreas Jaekel } 897*6a6a51eeSAndreas Jaekel create_tmp_queue = 0; 898a18c35b9SAndreas Jaekel break; 899add9520fSAndreas Jaekel case 'l': 900add9520fSAndreas Jaekel return zev_list_queues(fd); 901add9520fSAndreas Jaekel case 'Q': 902add9520fSAndreas Jaekel return zev_set_global_max_queue_len(fd, optarg); 903*6a6a51eeSAndreas Jaekel case 'L': 904add9520fSAndreas Jaekel return zev_set_max_queue_len(fd, optarg, argv[optind]); 905fec460f8SAndreas Jaekel case 't': 906add9520fSAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg, 907add9520fSAndreas Jaekel argv[optind]); 908a18c35b9SAndreas Jaekel case 'm': 909a18c35b9SAndreas Jaekel return zev_mute_pool(fd, optarg); 910a18c35b9SAndreas Jaekel case 'M': 911a18c35b9SAndreas Jaekel return zev_unmute_pool(fd, optarg); 912888fea18SAndreas Jaekel case 'k': 913888fea18SAndreas Jaekel return zev_mark(fd, optarg); 914add9520fSAndreas Jaekel case 'a': 915*6a6a51eeSAndreas Jaekel return zev_add_queue(fd, optarg, 0); 916*6a6a51eeSAndreas Jaekel case 'A': 917*6a6a51eeSAndreas Jaekel return zev_add_queue(fd, optarg, 1); 918add9520fSAndreas Jaekel case 'r': 919add9520fSAndreas Jaekel return zev_remove_queue(fd, optarg); 920add9520fSAndreas Jaekel case 'b': 921add9520fSAndreas Jaekel return zev_queue_blocking(fd, optarg, 0); 922add9520fSAndreas Jaekel case 'B': 923add9520fSAndreas Jaekel return zev_queue_blocking(fd, optarg, 1); 924add9520fSAndreas Jaekel case 'P': 925add9520fSAndreas Jaekel return zev_queue_properties(fd, optarg); 926a18c35b9SAndreas Jaekel case 'h': 927a18c35b9SAndreas Jaekel case '?': 928a18c35b9SAndreas Jaekel default: 929a18c35b9SAndreas Jaekel usage(argv[0]); 930a18c35b9SAndreas Jaekel } 931a18c35b9SAndreas Jaekel } 932a18c35b9SAndreas Jaekel usage(argv[0]); 933a18c35b9SAndreas Jaekel close(fd); 934add9520fSAndreas Jaekel return EXIT_FAILURE; 935a18c35b9SAndreas Jaekel } 936a18c35b9SAndreas Jaekel 937