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