1*2bb8e5e2SAndreas Jaekel #include <stdio.h> 2*2bb8e5e2SAndreas Jaekel #include <unistd.h> 3*2bb8e5e2SAndreas Jaekel #include <stdlib.h> 4*2bb8e5e2SAndreas Jaekel #include <fcntl.h> 5*2bb8e5e2SAndreas Jaekel #include <stropts.h> 6*2bb8e5e2SAndreas Jaekel #include <poll.h> 7*2bb8e5e2SAndreas Jaekel #include <string.h> 8*2bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h> 9*2bb8e5e2SAndreas Jaekel #include <errno.h> 10*2bb8e5e2SAndreas Jaekel 11*2bb8e5e2SAndreas Jaekel #define OP_STATISTICS (1 << 0) 12*2bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS (1 << 1) 13*2bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL (1 << 2) 14*2bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL (1 << 3) 15*2bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN (1 << 4) 16*2bb8e5e2SAndreas Jaekel 17*2bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev" 18*2bb8e5e2SAndreas Jaekel 19*2bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE; 20*2bb8e5e2SAndreas Jaekel 21*2bb8e5e2SAndreas Jaekel static void 22*2bb8e5e2SAndreas Jaekel zev_statistics(int fd) 23*2bb8e5e2SAndreas Jaekel { 24*2bb8e5e2SAndreas Jaekel zev_statistics_t zs; 25*2bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) { 26*2bb8e5e2SAndreas Jaekel perror("getting statistics data failed"); 27*2bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 28*2bb8e5e2SAndreas Jaekel } 29*2bb8e5e2SAndreas Jaekel printf("ZEV module state:\n"); 30*2bb8e5e2SAndreas Jaekel 31*2bb8e5e2SAndreas Jaekel printf(" queue length in bytes : %lu\n", zs.zev_queue_len); 32*2bb8e5e2SAndreas Jaekel printf(" queue length limit : %lu\n", zs.zev_max_queue_len); 33*2bb8e5e2SAndreas Jaekel printf(" bytes read from device : %lu\n", zs.zev_bytes_read); 34*2bb8e5e2SAndreas Jaekel printf(" module internal errors : %lu\n\n", zs.zev_cnt_errors); 35*2bb8e5e2SAndreas Jaekel 36*2bb8e5e2SAndreas Jaekel printf("ZFS event statistics:\n"); 37*2bb8e5e2SAndreas Jaekel 38*2bb8e5e2SAndreas Jaekel printf(" total ZFS events : %lu\n", zs.zev_cnt_total_events); 39*2bb8e5e2SAndreas Jaekel printf(" ZFS mount : %lu\n", zs.zev_cnt_zfs_mount); 40*2bb8e5e2SAndreas Jaekel printf(" ZFS umount : %lu\n", zs.zev_cnt_zfs_umount); 41*2bb8e5e2SAndreas Jaekel printf(" ZVOL write : %lu\n", zs.zev_cnt_zvol_write); 42*2bb8e5e2SAndreas Jaekel printf(" ZVOL truncate : %lu\n", zs.zev_cnt_zvol_truncate); 43*2bb8e5e2SAndreas Jaekel printf(" ZNODE close after update: %lu\n", 44*2bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_close_after_update); 45*2bb8e5e2SAndreas Jaekel printf(" ZNODE create : %lu\n", zs.zev_cnt_znode_create); 46*2bb8e5e2SAndreas Jaekel printf(" ZNODE remove : %lu\n", zs.zev_cnt_znode_remove); 47*2bb8e5e2SAndreas Jaekel printf(" ZNODE link : %lu\n", zs.zev_cnt_znode_link); 48*2bb8e5e2SAndreas Jaekel printf(" ZNODE symlink : %lu\n", zs.zev_cnt_znode_symlink); 49*2bb8e5e2SAndreas Jaekel printf(" ZNODE rename : %lu\n", zs.zev_cnt_znode_rename); 50*2bb8e5e2SAndreas Jaekel printf(" ZNODE write : %lu\n", zs.zev_cnt_znode_write); 51*2bb8e5e2SAndreas Jaekel printf(" ZNODE truncate : %lu\n", 52*2bb8e5e2SAndreas Jaekel zs.zev_cnt_znode_truncate); 53*2bb8e5e2SAndreas Jaekel printf(" ZNODE setattr : %lu\n", zs.zev_cnt_znode_setattr); 54*2bb8e5e2SAndreas Jaekel printf(" ZNODE acl : %lu\n", zs.zev_cnt_znode_acl); 55*2bb8e5e2SAndreas Jaekel } 56*2bb8e5e2SAndreas Jaekel 57*2bb8e5e2SAndreas Jaekel static void 58*2bb8e5e2SAndreas Jaekel zev_poll_events(int fd) 59*2bb8e5e2SAndreas Jaekel { 60*2bb8e5e2SAndreas Jaekel struct pollfd pfd[1]; 61*2bb8e5e2SAndreas Jaekel int ret; 62*2bb8e5e2SAndreas Jaekel char buf[1024]; 63*2bb8e5e2SAndreas Jaekel while (1) { 64*2bb8e5e2SAndreas Jaekel pfd[0].fd = fd; 65*2bb8e5e2SAndreas Jaekel pfd[0].events = POLLIN; 66*2bb8e5e2SAndreas Jaekel ret = poll(pfd, 1, 1000); 67*2bb8e5e2SAndreas Jaekel if (ret < 0) { 68*2bb8e5e2SAndreas Jaekel perror("poll failed"); 69*2bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 70*2bb8e5e2SAndreas Jaekel } 71*2bb8e5e2SAndreas Jaekel if (!(pfd[0].revents & POLLIN)) 72*2bb8e5e2SAndreas Jaekel continue; 73*2bb8e5e2SAndreas Jaekel /* data available */ 74*2bb8e5e2SAndreas Jaekel ret = read(fd, buf, sizeof(buf)); 75*2bb8e5e2SAndreas Jaekel if (ret < 0) { 76*2bb8e5e2SAndreas Jaekel perror("read failed"); 77*2bb8e5e2SAndreas Jaekel exit(EXIT_FAILURE); 78*2bb8e5e2SAndreas Jaekel } 79*2bb8e5e2SAndreas Jaekel if (ret == 0) 80*2bb8e5e2SAndreas Jaekel continue; 81*2bb8e5e2SAndreas Jaekel write(fileno(stdout), buf, ret); 82*2bb8e5e2SAndreas Jaekel } 83*2bb8e5e2SAndreas Jaekel return; 84*2bb8e5e2SAndreas Jaekel } 85*2bb8e5e2SAndreas Jaekel 86*2bb8e5e2SAndreas Jaekel static void 87*2bb8e5e2SAndreas Jaekel usage(char *progname) 88*2bb8e5e2SAndreas Jaekel { 89*2bb8e5e2SAndreas Jaekel fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname); 90*2bb8e5e2SAndreas Jaekel fprintf(stderr, " -s show zev statistics\n"); 91*2bb8e5e2SAndreas Jaekel fprintf(stderr, " -p poll for ZFS events\n"); 92*2bb8e5e2SAndreas Jaekel fprintf(stderr, " -q <bytes> set maximum event queue length\n"); 93*2bb8e5e2SAndreas Jaekel fprintf(stderr, " -m <pool> mute pool, no events for this pool\n"); 94*2bb8e5e2SAndreas Jaekel fprintf(stderr, " -M <pool> unmute pool\n"); 95*2bb8e5e2SAndreas Jaekel fprintf(stderr, " -d <dev> device file to use. default is '%s'\n", 96*2bb8e5e2SAndreas Jaekel ZEV_DEVICE); 97*2bb8e5e2SAndreas Jaekel exit (EXIT_FAILURE); 98*2bb8e5e2SAndreas Jaekel } 99*2bb8e5e2SAndreas Jaekel 100*2bb8e5e2SAndreas Jaekel static int 101*2bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg) 102*2bb8e5e2SAndreas Jaekel { 103*2bb8e5e2SAndreas Jaekel uint64_t maxqueuelen; 104*2bb8e5e2SAndreas Jaekel 105*2bb8e5e2SAndreas Jaekel errno = 0; 106*2bb8e5e2SAndreas Jaekel maxqueuelen = strtol(optarg, (char **)NULL, 10); 107*2bb8e5e2SAndreas Jaekel if (errno) { 108*2bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid queue length parameter: %s\n", optarg); 109*2bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 110*2bb8e5e2SAndreas Jaekel } 111*2bb8e5e2SAndreas Jaekel if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) { 112*2bb8e5e2SAndreas Jaekel perror("setting max queue length failed"); 113*2bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 114*2bb8e5e2SAndreas Jaekel } 115*2bb8e5e2SAndreas Jaekel return (0); 116*2bb8e5e2SAndreas Jaekel } 117*2bb8e5e2SAndreas Jaekel 118*2bb8e5e2SAndreas Jaekel static int 119*2bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute) 120*2bb8e5e2SAndreas Jaekel { 121*2bb8e5e2SAndreas Jaekel zev_ioctl_poolarg_t pa; 122*2bb8e5e2SAndreas Jaekel int len; 123*2bb8e5e2SAndreas Jaekel int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL; 124*2bb8e5e2SAndreas Jaekel len = strlen(poolname); 125*2bb8e5e2SAndreas Jaekel if (len <= 0 || len >= sizeof(pa.zev_poolname)) { 126*2bb8e5e2SAndreas Jaekel fprintf(stderr, "invalid poolname: %s\n", poolname); 127*2bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 128*2bb8e5e2SAndreas Jaekel } 129*2bb8e5e2SAndreas Jaekel strcpy(pa.zev_poolname, poolname); 130*2bb8e5e2SAndreas Jaekel pa.zev_poolname_len = len; 131*2bb8e5e2SAndreas Jaekel if (ioctl(fd, op, &pa)) { 132*2bb8e5e2SAndreas Jaekel perror("muting pool data failed"); 133*2bb8e5e2SAndreas Jaekel return (EXIT_FAILURE); 134*2bb8e5e2SAndreas Jaekel } 135*2bb8e5e2SAndreas Jaekel return (0); 136*2bb8e5e2SAndreas Jaekel } 137*2bb8e5e2SAndreas Jaekel 138*2bb8e5e2SAndreas Jaekel int 139*2bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname) 140*2bb8e5e2SAndreas Jaekel { 141*2bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 1); 142*2bb8e5e2SAndreas Jaekel } 143*2bb8e5e2SAndreas Jaekel 144*2bb8e5e2SAndreas Jaekel int 145*2bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname) 146*2bb8e5e2SAndreas Jaekel { 147*2bb8e5e2SAndreas Jaekel return zev_mute_unmute_impl(fd, poolname, 0); 148*2bb8e5e2SAndreas Jaekel } 149*2bb8e5e2SAndreas Jaekel 150*2bb8e5e2SAndreas Jaekel int 151*2bb8e5e2SAndreas Jaekel main(int argc, char **argv) 152*2bb8e5e2SAndreas Jaekel { 153*2bb8e5e2SAndreas Jaekel int fd; 154*2bb8e5e2SAndreas Jaekel int c; 155*2bb8e5e2SAndreas Jaekel int ops = 0; 156*2bb8e5e2SAndreas Jaekel extern char *optarg; 157*2bb8e5e2SAndreas Jaekel 158*2bb8e5e2SAndreas Jaekel /* open device */ 159*2bb8e5e2SAndreas Jaekel fd = open(zev_device, O_RDONLY); 160*2bb8e5e2SAndreas Jaekel if (fd < 0) { 161*2bb8e5e2SAndreas Jaekel perror("opening zev device failed"); 162*2bb8e5e2SAndreas Jaekel return EXIT_FAILURE; 163*2bb8e5e2SAndreas Jaekel } 164*2bb8e5e2SAndreas Jaekel while ((c = getopt(argc, argv, "spdq:m:M:h?")) != -1) { 165*2bb8e5e2SAndreas Jaekel switch(c) { 166*2bb8e5e2SAndreas Jaekel case 's': 167*2bb8e5e2SAndreas Jaekel ops |= OP_STATISTICS; 168*2bb8e5e2SAndreas Jaekel break; 169*2bb8e5e2SAndreas Jaekel case 'p': 170*2bb8e5e2SAndreas Jaekel ops |= OP_POLL_EVENTS; 171*2bb8e5e2SAndreas Jaekel break; 172*2bb8e5e2SAndreas Jaekel case 'd': 173*2bb8e5e2SAndreas Jaekel zev_device = optarg; 174*2bb8e5e2SAndreas Jaekel break; 175*2bb8e5e2SAndreas Jaekel case 'q': 176*2bb8e5e2SAndreas Jaekel return zev_set_max_queue_len(fd, optarg); 177*2bb8e5e2SAndreas Jaekel case 'm': 178*2bb8e5e2SAndreas Jaekel return zev_mute_pool(fd, optarg); 179*2bb8e5e2SAndreas Jaekel case 'M': 180*2bb8e5e2SAndreas Jaekel return zev_unmute_pool(fd, optarg); 181*2bb8e5e2SAndreas Jaekel case 'h': 182*2bb8e5e2SAndreas Jaekel case '?': 183*2bb8e5e2SAndreas Jaekel default: 184*2bb8e5e2SAndreas Jaekel usage(argv[0]); 185*2bb8e5e2SAndreas Jaekel } 186*2bb8e5e2SAndreas Jaekel } 187*2bb8e5e2SAndreas Jaekel if (!ops) 188*2bb8e5e2SAndreas Jaekel usage(argv[0]); 189*2bb8e5e2SAndreas Jaekel if (ops & OP_STATISTICS) 190*2bb8e5e2SAndreas Jaekel zev_statistics(fd); 191*2bb8e5e2SAndreas Jaekel if (ops & OP_POLL_EVENTS) 192*2bb8e5e2SAndreas Jaekel zev_poll_events(fd); 193*2bb8e5e2SAndreas Jaekel close(fd); 194*2bb8e5e2SAndreas Jaekel return EXIT_SUCCESS; 195*2bb8e5e2SAndreas Jaekel } 196*2bb8e5e2SAndreas Jaekel 197