12bb8e5e2SAndreas Jaekel #include <stdio.h> 22bb8e5e2SAndreas Jaekel #include <unistd.h> 32bb8e5e2SAndreas Jaekel #include <stdlib.h> 42bb8e5e2SAndreas Jaekel #include <fcntl.h> 52bb8e5e2SAndreas Jaekel #include <stropts.h> 62bb8e5e2SAndreas Jaekel #include <poll.h> 72bb8e5e2SAndreas Jaekel #include <string.h> 82bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h> 92bb8e5e2SAndreas Jaekel #include <errno.h> 102bb8e5e2SAndreas Jaekel 112bb8e5e2SAndreas Jaekel #define OP_STATISTICS (1 << 0) 122bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS (1 << 1) 132bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL (1 << 2) 142bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL (1 << 3) 152bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN (1 << 4) 162bb8e5e2SAndreas Jaekel 172bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev" 182bb8e5e2SAndreas Jaekel 192bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 202bb8e5e2SAndreas Jaekel 212bb8e5e2SAndreas Jaekel static void 222bb8e5e2SAndreas Jaekel zev_statistics(int fd) 232bb8e5e2SAndreas Jaekel { 242bb8e5e2SAndreas Jaekel zev_statistics_t zs; 252bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) { 262bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 272bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 282bb8e5e2SAndreas Jaekel } 292bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 302bb8e5e2SAndreas Jaekel 312bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 322bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 33*205a9bc9SAndreas Jaekel printf(" poll wakeup throttle : %lu\n\n", 34*205a9bc9SAndreas Jaekel zs.zev_poll_wakeup_queue_len); 352bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 362bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 372bb8e5e2SAndreas Jaekel 382bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 392bb8e5e2SAndreas Jaekel 402bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 412bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 422bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 432bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 442bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 452bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 462bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 472bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 482bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 492bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 502bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 512bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 522bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 532bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 542bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 552bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 562bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 572bb8e5e2SAndreas Jaekel } 582bb8e5e2SAndreas Jaekel 592bb8e5e2SAndreas Jaekel static void 602bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 612bb8e5e2SAndreas Jaekel { 622bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 632bb8e5e2SAndreas Jaekel int ret; 642bb8e5e2SAndreas Jaekel char buf[1024]; 652bb8e5e2SAndreas Jaekel while (1) { 662bb8e5e2SAndreas Jaekel pfd[0].fd = fd; 672bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 682bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 692bb8e5e2SAndreas Jaekel if (ret < 0) { 702bb8e5e2SAndreas Jaekel perror("poll failed"); 712bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 722bb8e5e2SAndreas Jaekel } 732bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 742bb8e5e2SAndreas Jaekel continue; 752bb8e5e2SAndreas Jaekel /* data available */ 762bb8e5e2SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 772bb8e5e2SAndreas Jaekel if (ret < 0) { 782bb8e5e2SAndreas Jaekel perror("read failed"); 792bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 802bb8e5e2SAndreas Jaekel } 812bb8e5e2SAndreas Jaekel if (ret == 0) 822bb8e5e2SAndreas Jaekel continue; 832bb8e5e2SAndreas Jaekel write(fileno(stdout), buf, ret); 842bb8e5e2SAndreas Jaekel } 852bb8e5e2SAndreas Jaekel return; 862bb8e5e2SAndreas Jaekel } 872bb8e5e2SAndreas Jaekel 882bb8e5e2SAndreas Jaekel static void 892bb8e5e2SAndreas Jaekel usage(char *progname) 902bb8e5e2SAndreas Jaekel { 912bb8e5e2SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 922bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 932bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 942bb8e5e2SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 95*205a9bc9SAndreas Jaekel fprintf(stderr, " -t <bytes> set queue length poll throttle\n"); 962bb8e5e2SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 972bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 982bb8e5e2SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 992bb8e5e2SAndreas Jaekel ZEV_DEVICE); 1002bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 1012bb8e5e2SAndreas Jaekel } 1022bb8e5e2SAndreas Jaekel 1032bb8e5e2SAndreas Jaekel static int 1042bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 1052bb8e5e2SAndreas Jaekel { 1062bb8e5e2SAndreas Jaekel uint64_t maxqueuelen; 1072bb8e5e2SAndreas Jaekel 1082bb8e5e2SAndreas Jaekel errno = 0; 1092bb8e5e2SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 1102bb8e5e2SAndreas Jaekel if (errno) { 1112bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 1122bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 1132bb8e5e2SAndreas Jaekel } 1142bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 1152bb8e5e2SAndreas Jaekel perror("setting max queue length failed"); 1162bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 1172bb8e5e2SAndreas Jaekel } 1182bb8e5e2SAndreas Jaekel return (0); 1192bb8e5e2SAndreas Jaekel } 1202bb8e5e2SAndreas Jaekel 1212bb8e5e2SAndreas Jaekel static int 122*205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg) 123*205a9bc9SAndreas Jaekel { 124*205a9bc9SAndreas Jaekel uint64_t queuelen; 125*205a9bc9SAndreas Jaekel 126*205a9bc9SAndreas Jaekel errno = 0; 127*205a9bc9SAndreas Jaekel queuelen = strtol(optarg, (char **)NULL, 10); 128*205a9bc9SAndreas Jaekel if (errno) { 129*205a9bc9SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 130*205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 131*205a9bc9SAndreas Jaekel } 132*205a9bc9SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) { 133*205a9bc9SAndreas Jaekel perror("setting poll wakeup queue length failed"); 134*205a9bc9SAndreas Jaekel return (EXIT_FAILURE); 135*205a9bc9SAndreas Jaekel } 136*205a9bc9SAndreas Jaekel return (0); 137*205a9bc9SAndreas Jaekel } 138*205a9bc9SAndreas Jaekel 139*205a9bc9SAndreas Jaekel static int 1402bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 1412bb8e5e2SAndreas Jaekel { 1422bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 1432bb8e5e2SAndreas Jaekel int len; 1442bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 1452bb8e5e2SAndreas Jaekel len = strlen(poolname); 1462bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 1472bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 1482bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 1492bb8e5e2SAndreas Jaekel } 1502bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 1512bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 1522bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 1532bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 1542bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 1552bb8e5e2SAndreas Jaekel } 1562bb8e5e2SAndreas Jaekel return (0); 1572bb8e5e2SAndreas Jaekel } 1582bb8e5e2SAndreas Jaekel 1592bb8e5e2SAndreas Jaekel int 1602bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 1612bb8e5e2SAndreas Jaekel { 1622bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 1632bb8e5e2SAndreas Jaekel } 1642bb8e5e2SAndreas Jaekel 1652bb8e5e2SAndreas Jaekel int 1662bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 1672bb8e5e2SAndreas Jaekel { 1682bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 1692bb8e5e2SAndreas Jaekel } 1702bb8e5e2SAndreas Jaekel 1712bb8e5e2SAndreas Jaekel int 1722bb8e5e2SAndreas Jaekel main(int argc, char **argv) 1732bb8e5e2SAndreas Jaekel { 1742bb8e5e2SAndreas Jaekel int fd; 1752bb8e5e2SAndreas Jaekel int c; 1762bb8e5e2SAndreas Jaekel int ops = 0; 1772bb8e5e2SAndreas Jaekel extern char *optarg; 1782bb8e5e2SAndreas Jaekel 1792bb8e5e2SAndreas Jaekel /* open device */ 1802bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 1812bb8e5e2SAndreas Jaekel if (fd < 0) { 1822bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 1832bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 1842bb8e5e2SAndreas Jaekel } 185*205a9bc9SAndreas Jaekel while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) { 1862bb8e5e2SAndreas Jaekel switch(c) { 1872bb8e5e2SAndreas Jaekel case 's': 1882bb8e5e2SAndreas Jaekel ops |= OP_STATISTICS; 1892bb8e5e2SAndreas Jaekel break; 1902bb8e5e2SAndreas Jaekel case 'p': 1912bb8e5e2SAndreas Jaekel ops |= OP_POLL_EVENTS; 1922bb8e5e2SAndreas Jaekel break; 1932bb8e5e2SAndreas Jaekel case 'd': 1942bb8e5e2SAndreas Jaekel zev_device = optarg; 1952bb8e5e2SAndreas Jaekel break; 1962bb8e5e2SAndreas Jaekel case 'q': 1972bb8e5e2SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 198*205a9bc9SAndreas Jaekel case 't': 199*205a9bc9SAndreas Jaekel return zev_set_poll_wakeup_queue_len(fd, optarg); 2002bb8e5e2SAndreas Jaekel case 'm': 2012bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 2022bb8e5e2SAndreas Jaekel case 'M': 2032bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 2042bb8e5e2SAndreas Jaekel case 'h': 2052bb8e5e2SAndreas Jaekel case '?': 2062bb8e5e2SAndreas Jaekel default: 2072bb8e5e2SAndreas Jaekel usage(argv[0]); 2082bb8e5e2SAndreas Jaekel } 2092bb8e5e2SAndreas Jaekel } 2102bb8e5e2SAndreas Jaekel if (!ops) 2112bb8e5e2SAndreas Jaekel usage(argv[0]); 2122bb8e5e2SAndreas Jaekel if (ops & OP_STATISTICS) 2132bb8e5e2SAndreas Jaekel zev_statistics(fd); 2142bb8e5e2SAndreas Jaekel if (ops & OP_POLL_EVENTS) 2152bb8e5e2SAndreas Jaekel zev_poll_events(fd); 2162bb8e5e2SAndreas Jaekel close(fd); 2172bb8e5e2SAndreas Jaekel return EXIT_SUCCESS; 2182bb8e5e2SAndreas Jaekel } 2192bb8e5e2SAndreas Jaekel 220