xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision aafc540fedcd29b30eb3e489b51908a545618f14)
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>
10*aafc540fSAndreas Jaekel #include <libnvpair.h>
11a18c35b9SAndreas Jaekel 
12a18c35b9SAndreas Jaekel #define OP_STATISTICS		(1 << 0)
13a18c35b9SAndreas Jaekel #define OP_POLL_EVENTS		(1 << 1)
14a18c35b9SAndreas Jaekel #define OP_MUTE_POOL		(1 << 2)
15a18c35b9SAndreas Jaekel #define OP_UNMUTE_POOL		(1 << 3)
16a18c35b9SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN	(1 << 4)
17a18c35b9SAndreas Jaekel 
18a18c35b9SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev"
19a18c35b9SAndreas Jaekel 
20a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
21a18c35b9SAndreas Jaekel 
22*aafc540fSAndreas Jaekel static char *zev_op_name[] = {
23*aafc540fSAndreas Jaekel 	"ZEV_OP_ERROR",
24*aafc540fSAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
25*aafc540fSAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
26*aafc540fSAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
27*aafc540fSAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
28*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
29*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
30*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
31*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
32*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
33*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
34*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
35*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
36*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
37*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
38*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
39*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
40*aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
41*aafc540fSAndreas Jaekel 	NULL
42*aafc540fSAndreas Jaekel };
43*aafc540fSAndreas Jaekel 
44a18c35b9SAndreas Jaekel static void
45a18c35b9SAndreas Jaekel zev_statistics(int fd)
46a18c35b9SAndreas Jaekel {
47a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
48a18c35b9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
49a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
50a18c35b9SAndreas Jaekel 		exit (EXIT_FAILURE);
51a18c35b9SAndreas Jaekel 	}
52a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
53a18c35b9SAndreas Jaekel 
54a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
55a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
56fec460f8SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
57fec460f8SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
58a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
59a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
60a18c35b9SAndreas Jaekel 
61a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
62a18c35b9SAndreas Jaekel 
63a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
64a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
65a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
66a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
67a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
68a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
69a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
70a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
71a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
72a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
73a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
74a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
75a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
76a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
77a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
78a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
79a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
80a18c35b9SAndreas Jaekel }
81a18c35b9SAndreas Jaekel 
82a18c35b9SAndreas Jaekel static void
83*aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
84*aafc540fSAndreas Jaekel {
85*aafc540fSAndreas Jaekel 	nvlist_t *nvl;
86*aafc540fSAndreas Jaekel 	nvpair_t *curr, *next;
87*aafc540fSAndreas Jaekel 	int err;
88*aafc540fSAndreas Jaekel 	char *key;
89*aafc540fSAndreas Jaekel 	data_type_t type;
90*aafc540fSAndreas Jaekel 	uchar_t op;
91*aafc540fSAndreas Jaekel 	uint64_t op_time;
92*aafc540fSAndreas Jaekel 	char *when;
93*aafc540fSAndreas Jaekel 	time_t ot;
94*aafc540fSAndreas Jaekel 	boolean_t val_bool;
95*aafc540fSAndreas Jaekel 	uint64_t val_uint64;
96*aafc540fSAndreas Jaekel 	char *val_string;
97*aafc540fSAndreas Jaekel 	uchar_t val_byte;
98*aafc540fSAndreas Jaekel 	int32_t val_int32;
99*aafc540fSAndreas Jaekel 
100*aafc540fSAndreas Jaekel 	if (0 != nvlist_unpack(buf, len, &nvl, NV_ENCODE_NATIVE)) {
101*aafc540fSAndreas Jaekel 		fprintf(stderr, "zev event garbled: can't unpack nvlist\n");
102*aafc540fSAndreas Jaekel 		exit(1);
103*aafc540fSAndreas Jaekel 	}
104*aafc540fSAndreas Jaekel 
105*aafc540fSAndreas Jaekel 	if (0 != nvlist_lookup_byte(nvl, "op", &op)) {
106*aafc540fSAndreas Jaekel 		fprintf(stderr, "zev event garbled: no op specified\n");
107*aafc540fSAndreas Jaekel 		exit(1);
108*aafc540fSAndreas Jaekel 	}
109*aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
110*aafc540fSAndreas Jaekel 		fprintf(stderr, "zev event garbled: op %d is outside range\n",
111*aafc540fSAndreas Jaekel 		        op);
112*aafc540fSAndreas Jaekel 		exit(1);
113*aafc540fSAndreas Jaekel 	}
114*aafc540fSAndreas Jaekel 	if (0 != nvlist_lookup_uint64(nvl, "op_time", &op_time)) {
115*aafc540fSAndreas Jaekel 		fprintf(stderr, "zev event garbled: no op_time specified\n");
116*aafc540fSAndreas Jaekel 		exit(1);
117*aafc540fSAndreas Jaekel 	}
118*aafc540fSAndreas Jaekel 	ot = op_time;
119*aafc540fSAndreas Jaekel 	when = ctime(&ot);
120*aafc540fSAndreas Jaekel 	when[24] = '\0';
121*aafc540fSAndreas Jaekel 	printf("%s %s", when, zev_op_name[op - ZEV_OP_MIN]);
122*aafc540fSAndreas Jaekel 
123*aafc540fSAndreas Jaekel 	curr = nvlist_next_nvpair(nvl, NULL);
124*aafc540fSAndreas Jaekel 	while (curr != NULL) {
125*aafc540fSAndreas Jaekel 		nvpair_t *next = nvlist_next_nvpair(nvl, curr);
126*aafc540fSAndreas Jaekel 		key = nvpair_name(curr);
127*aafc540fSAndreas Jaekel 		if (!strcmp(key, "op"))
128*aafc540fSAndreas Jaekel 			goto skip;
129*aafc540fSAndreas Jaekel 		if (!strcmp(key, "op_time"))
130*aafc540fSAndreas Jaekel 			goto skip;
131*aafc540fSAndreas Jaekel 		type = nvpair_type(curr);
132*aafc540fSAndreas Jaekel 		switch (type) {
133*aafc540fSAndreas Jaekel 		case DATA_TYPE_BOOLEAN_VALUE:
134*aafc540fSAndreas Jaekel 			nvlist_lookup_boolean_value(nvl, key, &val_bool);
135*aafc540fSAndreas Jaekel 			printf(" %s=%s", key, (val_bool ? "true" : "false"));
136*aafc540fSAndreas Jaekel 			break;
137*aafc540fSAndreas Jaekel 		case DATA_TYPE_BYTE:
138*aafc540fSAndreas Jaekel 			nvlist_lookup_byte(nvl, key, &val_byte);
139*aafc540fSAndreas Jaekel 			printf(" %s=%d", key, val_byte);
140*aafc540fSAndreas Jaekel 			break;
141*aafc540fSAndreas Jaekel 		case DATA_TYPE_UINT64:
142*aafc540fSAndreas Jaekel 			nvlist_lookup_uint64(nvl, key, &val_uint64);
143*aafc540fSAndreas Jaekel 			printf(" %s=%llu", key, val_uint64);
144*aafc540fSAndreas Jaekel 			break;
145*aafc540fSAndreas Jaekel 		case DATA_TYPE_INT32:
146*aafc540fSAndreas Jaekel 			nvlist_lookup_int32(nvl, key, &val_int32);
147*aafc540fSAndreas Jaekel 			printf(" %s=%d", key, val_int32);
148*aafc540fSAndreas Jaekel 			break;
149*aafc540fSAndreas Jaekel 		case DATA_TYPE_STRING:
150*aafc540fSAndreas Jaekel 			nvlist_lookup_string(nvl, key, &val_string);
151*aafc540fSAndreas Jaekel 			printf(" %s=%s", key, val_string);
152*aafc540fSAndreas Jaekel 			break;
153*aafc540fSAndreas Jaekel 		default:
154*aafc540fSAndreas Jaekel 			fprintf(stderr, "unexpected nvlist data type: %d\n",
155*aafc540fSAndreas Jaekel 			        type);
156*aafc540fSAndreas Jaekel 			exit(1);
157*aafc540fSAndreas Jaekel 		}
158*aafc540fSAndreas Jaekel skip:
159*aafc540fSAndreas Jaekel 		curr = next;
160*aafc540fSAndreas Jaekel 	}
161*aafc540fSAndreas Jaekel 	printf("\n");
162*aafc540fSAndreas Jaekel }
163*aafc540fSAndreas Jaekel 
164*aafc540fSAndreas Jaekel static void
165a18c35b9SAndreas Jaekel zev_poll_events(int fd)
166a18c35b9SAndreas Jaekel {
167a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
168a18c35b9SAndreas Jaekel 	int ret;
169*aafc540fSAndreas Jaekel 	char buf[4096];
170a18c35b9SAndreas Jaekel 	while (1) {
171a18c35b9SAndreas Jaekel 		pfd[0].fd = fd;
172a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
173a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
174a18c35b9SAndreas Jaekel 		if (ret < 0) {
175a18c35b9SAndreas Jaekel 			perror("poll failed");
176a18c35b9SAndreas Jaekel 			exit(EXIT_FAILURE);
177a18c35b9SAndreas Jaekel 		}
178a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
179a18c35b9SAndreas Jaekel 			continue;
180a18c35b9SAndreas Jaekel 		/* data available */
181a18c35b9SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
182a18c35b9SAndreas Jaekel 		if (ret < 0) {
183a18c35b9SAndreas Jaekel 			perror("read failed");
184a18c35b9SAndreas Jaekel 			exit(EXIT_FAILURE);
185a18c35b9SAndreas Jaekel 		}
186a18c35b9SAndreas Jaekel 		if (ret == 0)
187a18c35b9SAndreas Jaekel 			continue;
188*aafc540fSAndreas Jaekel 		zev_print_event(buf, ret);
189a18c35b9SAndreas Jaekel 	}
190a18c35b9SAndreas Jaekel 	return;
191a18c35b9SAndreas Jaekel }
192a18c35b9SAndreas Jaekel 
193a18c35b9SAndreas Jaekel static void
194a18c35b9SAndreas Jaekel usage(char *progname)
195a18c35b9SAndreas Jaekel {
196a18c35b9SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
197a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
198a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
199a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
200fec460f8SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
201a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
202a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
203a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
204a18c35b9SAndreas Jaekel 	    ZEV_DEVICE);
205a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
206a18c35b9SAndreas Jaekel }
207a18c35b9SAndreas Jaekel 
208a18c35b9SAndreas Jaekel static int
209a18c35b9SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
210a18c35b9SAndreas Jaekel {
211a18c35b9SAndreas Jaekel 	uint64_t maxqueuelen;
212a18c35b9SAndreas Jaekel 
213a18c35b9SAndreas Jaekel 	errno = 0;
214a18c35b9SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
215a18c35b9SAndreas Jaekel 	if (errno) {
216a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
217a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
218a18c35b9SAndreas Jaekel 	}
219a18c35b9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
220a18c35b9SAndreas Jaekel 		perror("setting max queue length failed");
221a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
222a18c35b9SAndreas Jaekel 	}
223a18c35b9SAndreas Jaekel 	return (0);
224a18c35b9SAndreas Jaekel }
225a18c35b9SAndreas Jaekel 
226a18c35b9SAndreas Jaekel static int
227fec460f8SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
228fec460f8SAndreas Jaekel {
229fec460f8SAndreas Jaekel 	uint64_t queuelen;
230fec460f8SAndreas Jaekel 
231fec460f8SAndreas Jaekel 	errno = 0;
232fec460f8SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
233fec460f8SAndreas Jaekel 	if (errno) {
234fec460f8SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
235fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
236fec460f8SAndreas Jaekel 	}
237fec460f8SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
238fec460f8SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
239fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
240fec460f8SAndreas Jaekel 	}
241fec460f8SAndreas Jaekel 	return (0);
242fec460f8SAndreas Jaekel }
243fec460f8SAndreas Jaekel 
244fec460f8SAndreas Jaekel static int
245a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
246a18c35b9SAndreas Jaekel {
247a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
248a18c35b9SAndreas Jaekel 	int len;
249a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
250a18c35b9SAndreas Jaekel 	len = strlen(poolname);
251a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
252a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
253a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
254a18c35b9SAndreas Jaekel 	}
255a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
256a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
257a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
258a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
259a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
260a18c35b9SAndreas Jaekel 	}
261a18c35b9SAndreas Jaekel 	return (0);
262a18c35b9SAndreas Jaekel }
263a18c35b9SAndreas Jaekel 
264a18c35b9SAndreas Jaekel int
265a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
266a18c35b9SAndreas Jaekel {
267a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
268a18c35b9SAndreas Jaekel }
269a18c35b9SAndreas Jaekel 
270a18c35b9SAndreas Jaekel int
271a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
272a18c35b9SAndreas Jaekel {
273a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
274a18c35b9SAndreas Jaekel }
275a18c35b9SAndreas Jaekel 
276a18c35b9SAndreas Jaekel int
277a18c35b9SAndreas Jaekel main(int argc, char **argv)
278a18c35b9SAndreas Jaekel {
279a18c35b9SAndreas Jaekel 	int fd;
280a18c35b9SAndreas Jaekel 	int c;
281a18c35b9SAndreas Jaekel 	int ops = 0;
282a18c35b9SAndreas Jaekel 	extern char *optarg;
283a18c35b9SAndreas Jaekel 
284a18c35b9SAndreas Jaekel 	/* open device */
285a18c35b9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
286a18c35b9SAndreas Jaekel 	if (fd < 0) {
287a18c35b9SAndreas Jaekel 		perror("opening zev device failed");
288a18c35b9SAndreas Jaekel 		return EXIT_FAILURE;
289a18c35b9SAndreas Jaekel 	}
290fec460f8SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) {
291a18c35b9SAndreas Jaekel 		switch(c) {
292a18c35b9SAndreas Jaekel 		case 's':
293a18c35b9SAndreas Jaekel 			ops |= OP_STATISTICS;
294a18c35b9SAndreas Jaekel 			break;
295a18c35b9SAndreas Jaekel 		case 'p':
296a18c35b9SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
297a18c35b9SAndreas Jaekel 			break;
298a18c35b9SAndreas Jaekel 		case 'd':
299a18c35b9SAndreas Jaekel 			zev_device = optarg;
300a18c35b9SAndreas Jaekel 			break;
301a18c35b9SAndreas Jaekel 		case 'q':
302a18c35b9SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
303fec460f8SAndreas Jaekel 		case 't':
304fec460f8SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
305a18c35b9SAndreas Jaekel 		case 'm':
306a18c35b9SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
307a18c35b9SAndreas Jaekel 		case 'M':
308a18c35b9SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
309a18c35b9SAndreas Jaekel 		case 'h':
310a18c35b9SAndreas Jaekel 		case '?':
311a18c35b9SAndreas Jaekel 		default:
312a18c35b9SAndreas Jaekel 			usage(argv[0]);
313a18c35b9SAndreas Jaekel 		}
314a18c35b9SAndreas Jaekel 	}
315a18c35b9SAndreas Jaekel 	if (!ops)
316a18c35b9SAndreas Jaekel 		usage(argv[0]);
317a18c35b9SAndreas Jaekel 	if (ops & OP_STATISTICS)
318a18c35b9SAndreas Jaekel 		zev_statistics(fd);
319a18c35b9SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
320a18c35b9SAndreas Jaekel 		zev_poll_events(fd);
321a18c35b9SAndreas Jaekel 	close(fd);
322a18c35b9SAndreas Jaekel 	return EXIT_SUCCESS;
323a18c35b9SAndreas Jaekel }
324a18c35b9SAndreas Jaekel 
325