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