xref: /titanic_51/usr/src/cmd/zevadm/zevadm.c (revision 9193e9c2f160bcdc30e75eef8df0635e63f514a1)
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>
10*9193e9c2SAndreas Jaekel #include <libnvpair.h>
112bb8e5e2SAndreas Jaekel 
122bb8e5e2SAndreas Jaekel #define OP_STATISTICS		(1 << 0)
132bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS		(1 << 1)
142bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL		(1 << 2)
152bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL		(1 << 3)
162bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN	(1 << 4)
172bb8e5e2SAndreas Jaekel 
182bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev"
192bb8e5e2SAndreas Jaekel 
202bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
212bb8e5e2SAndreas Jaekel 
22*9193e9c2SAndreas Jaekel static char *zev_op_name[] = {
23*9193e9c2SAndreas Jaekel 	"ZEV_OP_ERROR",
24*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
25*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
26*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
27*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
28*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
29*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
30*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
31*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
32*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
33*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
34*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
35*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
36*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
37*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
38*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
39*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
40*9193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
41*9193e9c2SAndreas Jaekel 	NULL
42*9193e9c2SAndreas Jaekel };
43*9193e9c2SAndreas Jaekel 
442bb8e5e2SAndreas Jaekel static void
452bb8e5e2SAndreas Jaekel zev_statistics(int fd)
462bb8e5e2SAndreas Jaekel {
472bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
482bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
492bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
502bb8e5e2SAndreas Jaekel 		exit (EXIT_FAILURE);
512bb8e5e2SAndreas Jaekel 	}
522bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
532bb8e5e2SAndreas Jaekel 
542bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
552bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
56205a9bc9SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
57205a9bc9SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
582bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
592bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
602bb8e5e2SAndreas Jaekel 
612bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
622bb8e5e2SAndreas Jaekel 
632bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
642bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
652bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
662bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
672bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
682bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
692bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
702bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
712bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
722bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
732bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
742bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
752bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
762bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
772bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
782bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
792bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
802bb8e5e2SAndreas Jaekel }
812bb8e5e2SAndreas Jaekel 
822bb8e5e2SAndreas Jaekel static void
83*9193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
84*9193e9c2SAndreas Jaekel {
85*9193e9c2SAndreas Jaekel 	nvlist_t *nvl;
86*9193e9c2SAndreas Jaekel 	nvpair_t *curr, *next;
87*9193e9c2SAndreas Jaekel 	int err;
88*9193e9c2SAndreas Jaekel 	char *key;
89*9193e9c2SAndreas Jaekel 	data_type_t type;
90*9193e9c2SAndreas Jaekel 	uchar_t op;
91*9193e9c2SAndreas Jaekel 	uint64_t op_time;
92*9193e9c2SAndreas Jaekel 	char *when;
93*9193e9c2SAndreas Jaekel 	time_t ot;
94*9193e9c2SAndreas Jaekel 	boolean_t val_bool;
95*9193e9c2SAndreas Jaekel 	uint64_t val_uint64;
96*9193e9c2SAndreas Jaekel 	char *val_string;
97*9193e9c2SAndreas Jaekel 	uchar_t val_byte;
98*9193e9c2SAndreas Jaekel 	int32_t val_int32;
99*9193e9c2SAndreas Jaekel 
100*9193e9c2SAndreas Jaekel 	if (0 != nvlist_unpack(buf, len, &nvl, NV_ENCODE_NATIVE)) {
101*9193e9c2SAndreas Jaekel 		fprintf(stderr, "zev event garbled: can't unpack nvlist\n");
102*9193e9c2SAndreas Jaekel 		exit(1);
103*9193e9c2SAndreas Jaekel 	}
104*9193e9c2SAndreas Jaekel 
105*9193e9c2SAndreas Jaekel 	if (0 != nvlist_lookup_byte(nvl, "op", &op)) {
106*9193e9c2SAndreas Jaekel 		fprintf(stderr, "zev event garbled: no op specified\n");
107*9193e9c2SAndreas Jaekel 		exit(1);
108*9193e9c2SAndreas Jaekel 	}
109*9193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
110*9193e9c2SAndreas Jaekel 		fprintf(stderr, "zev event garbled: op %d is outside range\n",
111*9193e9c2SAndreas Jaekel 		        op);
112*9193e9c2SAndreas Jaekel 		exit(1);
113*9193e9c2SAndreas Jaekel 	}
114*9193e9c2SAndreas Jaekel 	if (0 != nvlist_lookup_uint64(nvl, "op_time", &op_time)) {
115*9193e9c2SAndreas Jaekel 		fprintf(stderr, "zev event garbled: no op_time specified\n");
116*9193e9c2SAndreas Jaekel 		exit(1);
117*9193e9c2SAndreas Jaekel 	}
118*9193e9c2SAndreas Jaekel 	ot = op_time;
119*9193e9c2SAndreas Jaekel 	when = ctime(&ot);
120*9193e9c2SAndreas Jaekel 	when[24] = '\0';
121*9193e9c2SAndreas Jaekel 	printf("%s %s", when, zev_op_name[op - ZEV_OP_MIN]);
122*9193e9c2SAndreas Jaekel 
123*9193e9c2SAndreas Jaekel 	curr = nvlist_next_nvpair(nvl, NULL);
124*9193e9c2SAndreas Jaekel 	while (curr != NULL) {
125*9193e9c2SAndreas Jaekel 		nvpair_t *next = nvlist_next_nvpair(nvl, curr);
126*9193e9c2SAndreas Jaekel 		key = nvpair_name(curr);
127*9193e9c2SAndreas Jaekel 		if (!strcmp(key, "op"))
128*9193e9c2SAndreas Jaekel 			goto skip;
129*9193e9c2SAndreas Jaekel 		if (!strcmp(key, "op_time"))
130*9193e9c2SAndreas Jaekel 			goto skip;
131*9193e9c2SAndreas Jaekel 		type = nvpair_type(curr);
132*9193e9c2SAndreas Jaekel 		switch (type) {
133*9193e9c2SAndreas Jaekel 		case DATA_TYPE_BOOLEAN_VALUE:
134*9193e9c2SAndreas Jaekel 			nvlist_lookup_boolean_value(nvl, key, &val_bool);
135*9193e9c2SAndreas Jaekel 			printf(" %s=%s", key, (val_bool ? "true" : "false"));
136*9193e9c2SAndreas Jaekel 			break;
137*9193e9c2SAndreas Jaekel 		case DATA_TYPE_BYTE:
138*9193e9c2SAndreas Jaekel 			nvlist_lookup_byte(nvl, key, &val_byte);
139*9193e9c2SAndreas Jaekel 			printf(" %s=%d", key, val_byte);
140*9193e9c2SAndreas Jaekel 			break;
141*9193e9c2SAndreas Jaekel 		case DATA_TYPE_UINT64:
142*9193e9c2SAndreas Jaekel 			nvlist_lookup_uint64(nvl, key, &val_uint64);
143*9193e9c2SAndreas Jaekel 			printf(" %s=%llu", key, val_uint64);
144*9193e9c2SAndreas Jaekel 			break;
145*9193e9c2SAndreas Jaekel 		case DATA_TYPE_INT32:
146*9193e9c2SAndreas Jaekel 			nvlist_lookup_int32(nvl, key, &val_int32);
147*9193e9c2SAndreas Jaekel 			printf(" %s=%d", key, val_int32);
148*9193e9c2SAndreas Jaekel 			break;
149*9193e9c2SAndreas Jaekel 		case DATA_TYPE_STRING:
150*9193e9c2SAndreas Jaekel 			nvlist_lookup_string(nvl, key, &val_string);
151*9193e9c2SAndreas Jaekel 			printf(" %s=%s", key, val_string);
152*9193e9c2SAndreas Jaekel 			break;
153*9193e9c2SAndreas Jaekel 		default:
154*9193e9c2SAndreas Jaekel 			fprintf(stderr, "unexpected nvlist data type: %d\n",
155*9193e9c2SAndreas Jaekel 			        type);
156*9193e9c2SAndreas Jaekel 			exit(1);
157*9193e9c2SAndreas Jaekel 		}
158*9193e9c2SAndreas Jaekel skip:
159*9193e9c2SAndreas Jaekel 		curr = next;
160*9193e9c2SAndreas Jaekel 	}
161*9193e9c2SAndreas Jaekel 	printf("\n");
162*9193e9c2SAndreas Jaekel }
163*9193e9c2SAndreas Jaekel 
164*9193e9c2SAndreas Jaekel static void
1652bb8e5e2SAndreas Jaekel zev_poll_events(int fd)
1662bb8e5e2SAndreas Jaekel {
1672bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
1682bb8e5e2SAndreas Jaekel 	int ret;
169*9193e9c2SAndreas Jaekel 	char buf[4096];
1702bb8e5e2SAndreas Jaekel 	while (1) {
1712bb8e5e2SAndreas Jaekel 		pfd[0].fd = fd;
1722bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
1732bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
1742bb8e5e2SAndreas Jaekel 		if (ret < 0) {
1752bb8e5e2SAndreas Jaekel 			perror("poll failed");
1762bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
1772bb8e5e2SAndreas Jaekel 		}
1782bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
1792bb8e5e2SAndreas Jaekel 			continue;
1802bb8e5e2SAndreas Jaekel 		/* data available */
1812bb8e5e2SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
1822bb8e5e2SAndreas Jaekel 		if (ret < 0) {
1832bb8e5e2SAndreas Jaekel 			perror("read failed");
1842bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
1852bb8e5e2SAndreas Jaekel 		}
1862bb8e5e2SAndreas Jaekel 		if (ret == 0)
1872bb8e5e2SAndreas Jaekel 			continue;
188*9193e9c2SAndreas Jaekel 		zev_print_event(buf, ret);
1892bb8e5e2SAndreas Jaekel 	}
1902bb8e5e2SAndreas Jaekel 	return;
1912bb8e5e2SAndreas Jaekel }
1922bb8e5e2SAndreas Jaekel 
1932bb8e5e2SAndreas Jaekel static void
1942bb8e5e2SAndreas Jaekel usage(char *progname)
1952bb8e5e2SAndreas Jaekel {
1962bb8e5e2SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
1972bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
1982bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
1992bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
200205a9bc9SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
2012bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
2022bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
2032bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
2042bb8e5e2SAndreas Jaekel 	    ZEV_DEVICE);
2052bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
2062bb8e5e2SAndreas Jaekel }
2072bb8e5e2SAndreas Jaekel 
2082bb8e5e2SAndreas Jaekel static int
2092bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
2102bb8e5e2SAndreas Jaekel {
2112bb8e5e2SAndreas Jaekel 	uint64_t maxqueuelen;
2122bb8e5e2SAndreas Jaekel 
2132bb8e5e2SAndreas Jaekel 	errno = 0;
2142bb8e5e2SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
2152bb8e5e2SAndreas Jaekel 	if (errno) {
2162bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
2172bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
2182bb8e5e2SAndreas Jaekel 	}
2192bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
2202bb8e5e2SAndreas Jaekel 		perror("setting max queue length failed");
2212bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
2222bb8e5e2SAndreas Jaekel 	}
2232bb8e5e2SAndreas Jaekel 	return (0);
2242bb8e5e2SAndreas Jaekel }
2252bb8e5e2SAndreas Jaekel 
2262bb8e5e2SAndreas Jaekel static int
227205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
228205a9bc9SAndreas Jaekel {
229205a9bc9SAndreas Jaekel 	uint64_t queuelen;
230205a9bc9SAndreas Jaekel 
231205a9bc9SAndreas Jaekel 	errno = 0;
232205a9bc9SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
233205a9bc9SAndreas Jaekel 	if (errno) {
234205a9bc9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
235205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
236205a9bc9SAndreas Jaekel 	}
237205a9bc9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
238205a9bc9SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
239205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
240205a9bc9SAndreas Jaekel 	}
241205a9bc9SAndreas Jaekel 	return (0);
242205a9bc9SAndreas Jaekel }
243205a9bc9SAndreas Jaekel 
244205a9bc9SAndreas Jaekel static int
2452bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
2462bb8e5e2SAndreas Jaekel {
2472bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
2482bb8e5e2SAndreas Jaekel 	int len;
2492bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
2502bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
2512bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
2522bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
2532bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
2542bb8e5e2SAndreas Jaekel 	}
2552bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
2562bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
2572bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
2582bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
2592bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
2602bb8e5e2SAndreas Jaekel 	}
2612bb8e5e2SAndreas Jaekel 	return (0);
2622bb8e5e2SAndreas Jaekel }
2632bb8e5e2SAndreas Jaekel 
2642bb8e5e2SAndreas Jaekel int
2652bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
2662bb8e5e2SAndreas Jaekel {
2672bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
2682bb8e5e2SAndreas Jaekel }
2692bb8e5e2SAndreas Jaekel 
2702bb8e5e2SAndreas Jaekel int
2712bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
2722bb8e5e2SAndreas Jaekel {
2732bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
2742bb8e5e2SAndreas Jaekel }
2752bb8e5e2SAndreas Jaekel 
2762bb8e5e2SAndreas Jaekel int
2772bb8e5e2SAndreas Jaekel main(int argc, char **argv)
2782bb8e5e2SAndreas Jaekel {
2792bb8e5e2SAndreas Jaekel 	int fd;
2802bb8e5e2SAndreas Jaekel 	int c;
2812bb8e5e2SAndreas Jaekel 	int ops = 0;
2822bb8e5e2SAndreas Jaekel 	extern char *optarg;
2832bb8e5e2SAndreas Jaekel 
2842bb8e5e2SAndreas Jaekel 	/* open device */
2852bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
2862bb8e5e2SAndreas Jaekel 	if (fd < 0) {
2872bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
2882bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
2892bb8e5e2SAndreas Jaekel 	}
290205a9bc9SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) {
2912bb8e5e2SAndreas Jaekel 		switch(c) {
2922bb8e5e2SAndreas Jaekel 		case 's':
2932bb8e5e2SAndreas Jaekel 			ops |= OP_STATISTICS;
2942bb8e5e2SAndreas Jaekel 			break;
2952bb8e5e2SAndreas Jaekel 		case 'p':
2962bb8e5e2SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
2972bb8e5e2SAndreas Jaekel 			break;
2982bb8e5e2SAndreas Jaekel 		case 'd':
2992bb8e5e2SAndreas Jaekel 			zev_device = optarg;
3002bb8e5e2SAndreas Jaekel 			break;
3012bb8e5e2SAndreas Jaekel 		case 'q':
3022bb8e5e2SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
303205a9bc9SAndreas Jaekel 		case 't':
304205a9bc9SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
3052bb8e5e2SAndreas Jaekel 		case 'm':
3062bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
3072bb8e5e2SAndreas Jaekel 		case 'M':
3082bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
3092bb8e5e2SAndreas Jaekel 		case 'h':
3102bb8e5e2SAndreas Jaekel 		case '?':
3112bb8e5e2SAndreas Jaekel 		default:
3122bb8e5e2SAndreas Jaekel 			usage(argv[0]);
3132bb8e5e2SAndreas Jaekel 		}
3142bb8e5e2SAndreas Jaekel 	}
3152bb8e5e2SAndreas Jaekel 	if (!ops)
3162bb8e5e2SAndreas Jaekel 		usage(argv[0]);
3172bb8e5e2SAndreas Jaekel 	if (ops & OP_STATISTICS)
3182bb8e5e2SAndreas Jaekel 		zev_statistics(fd);
3192bb8e5e2SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
3202bb8e5e2SAndreas Jaekel 		zev_poll_events(fd);
3212bb8e5e2SAndreas Jaekel 	close(fd);
3222bb8e5e2SAndreas Jaekel 	return EXIT_SUCCESS;
3232bb8e5e2SAndreas Jaekel }
3242bb8e5e2SAndreas Jaekel 
325