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