xref: /titanic_51/usr/src/cmd/zevadm/zevadm.c (revision 0abdde4ada1f3fbbe64a4bdddf53bb43bb73262a)
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 #include <sys/sysmacros.h>
11 #include <stdarg.h>
12 #include <sys/avl.h>
13 
14 #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
15 
16 #if !defined(offsetof)
17 #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
18 #endif
19 
20 static char *zev_device = ZEV_DEVICE;
21 
22 static char *zev_op_name[] = {
23 	"ERROR",
24 	"MARK",
25 	"ZFS_MOUNT",
26 	"ZFS_UMOUNT",
27 	"ZVOL_WRITE",
28 	"ZVOL_TRUNCATE",
29 	"ZNODE_CLOSE_AFTER_UPDATE",
30 	"ZNODE_CREATE",
31 	"ZNODE_MKDIR",
32 	"ZNODE_MAKE_XATTR_DIR",
33 	"ZNODE_REMOVE",
34 	"ZNODE_RMDIR",
35 	"ZNODE_LINK",
36 	"ZNODE_SYMLINK",
37 	"ZNODE_RENAME",
38 	"ZNODE_WRITE",
39 	"ZNODE_TRUNCATE",
40 	"ZNODE_SETATTR",
41 	"ZNODE_ACL",
42 	NULL
43 };
44 
45 #define MD_STATISTICS			1
46 #define MD_POLL_EVENTS			2
47 #define MD_CHECKSUMS			3
48 #define MD_DEBUG_INFO			4
49 #define MD_LIST_QUEUES			5
50 #define MD_SET_GLOBAL_MAX_QUEUE_LEN	6
51 #define MD_SET_MAX_QUEUE_LEN		7
52 #define MD_SET_POLL_WAKEUP_QUEUE_LEN	8
53 #define MD_MUTE_POOL			9
54 #define MD_UNMUTE_POOL			10
55 #define MD_MARK				11
56 #define MD_ADD_QUEUE			12
57 #define MD_ADD_BLOCKING_QUEUE		13
58 #define MD_REMOVE_QUEUE			14
59 #define MD_QUEUE_BLOCKING		15
60 #define MD_QUEUE_NONBLOCKING		16
61 #define MD_QUEUE_PROPERTIES		17
62 #define MD_ZEVSTAT			18
63 
64 static int verbose = 0;
65 static int grep_friendly = 0;
66 
67 static void
68 zpf(char *fmt, ...)
69 {
70 	va_list	ap;
71 
72 	va_start(ap, fmt);
73 	vprintf(fmt, ap);
74 	va_end(ap);
75 	if (grep_friendly) {
76 		printf(" ");
77 	} else {
78 		printf("\n");
79 	}
80 }
81 
82 static void
83 znl(void)
84 {
85 	if (grep_friendly)
86 		printf("\n");
87 }
88 
89 static void
90 sig2hex_direct(const uint8_t *sig, char *hex)
91 {
92 	int     i;
93 
94 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
95 		sprintf(hex + 2 * i, "%02x", sig[i]);
96 	}
97 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
98 }
99 
100 static int
101 zev_statistics(int fd)
102 {
103 	zev_statistics_t zs;
104 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
105 		perror("getting statistics data failed");
106 		return (EXIT_FAILURE);
107 	}
108 	printf("ZEV module state:\n");
109 
110 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
111 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
112 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
113 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
114 
115 	printf("    discarded events        : %lu\n",
116 	    zs.zev_cnt_discarded_events);
117 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
118 
119 	printf("ZFS event statistics:\n");
120 
121 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
122 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
123 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
124 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
125 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
126 	printf("    ZNODE close after update: %lu\n",
127 	    zs.zev_cnt_znode_close_after_update);
128 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
129 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
130 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
131 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
132 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
133 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
134 	printf("    ZNODE truncate          : %lu\n",
135 	    zs.zev_cnt_znode_truncate);
136 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
137 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
138 	return EXIT_SUCCESS;
139 }
140 
141 static void
142 zev_print_inode_info(char *name, zev_inode_info_t *info)
143 {
144 	zpf("  %s.inode: %llu", name, info->ino);
145 	zpf("  %s.gen: %llu", name, info->gen);
146 	zpf("  %s.mtime: %llu", name, info->mtime);
147 	zpf("  %s.ctime: %llu", name, info->ctime);
148 	zpf("  %s.size: %llu", name, info->size);
149 	zpf("  %s.mode: %llo", name, info->mode);
150 	zpf("  %s.links: %llu", name, info->links);
151 	zpf("  %s.type: %lu", name, info->type);
152 	zpf("  %s.flags: %lu", name, info->flags);
153 }
154 
155 static void
156 zev_print_mark_payload(zev_mark_t *rec)
157 {
158 	int i;
159 	int j;
160 	uint8_t *p;
161 	char c;
162 
163 	zpf("  payload:");
164 	p = (uint8_t *)ZEV_PAYLOAD(rec);
165 	for (i=0; i<rec->payload_len; i+=16) {
166 		printf("  ");
167 		for (j=i; j<rec->payload_len && j<i+16; j++) {
168 			printf("%02x ", p[j]);
169 			if (j == i + 7)
170 				printf(" ");
171 		}
172 		if (grep_friendly)
173 			continue;
174 		for (; j<i+16; j++) {
175 			printf("   ");
176 			if (j == i + 7)
177 				printf(" ");
178 		}
179 		printf("    ");
180 		for (j=i; j<rec->payload_len && j<i+16; j++) {
181 			c = '.';
182 			if (p[j] >= ' ' && p[j] <= '~')
183 				c = p[j];
184 			printf("%c", c);
185 			if (j == i + 7)
186 				printf(" ");
187 		}
188 		printf("\n");
189 	}
190 }
191 
192 static void
193 zev_print_error(char *buf)
194 {
195 	zev_error_t *rec = (zev_error_t *)buf;
196 	time_t op_time = rec->op_time;
197 	char *ct = ctime(&op_time); ct[24] = '\0';
198 
199 	if (verbose) {
200 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
201 		zpf("  guid: %llu", rec->guid);
202 		zpf("  failed.op: %s",
203 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
204 		zpf("  message: %s", ZEV_ERRSTR(rec));
205 		znl();
206 	} else {
207 		printf("%s %s: failed_op=%s msg=%s\n",
208 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
209 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
210 		       ZEV_ERRSTR(rec));
211 	}
212 }
213 
214 static void
215 zev_print_mark(char *buf)
216 {
217 	zev_mark_t *rec = (zev_mark_t *)buf;
218 	time_t op_time = rec->op_time;
219 	char *ct = ctime(&op_time); ct[24] = '\0';
220 
221 	if (verbose) {
222 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
223 		zpf("  guid: %llu", rec->guid);
224 		zpf("  mark.id: %llu", rec->mark_id);
225 		zpf("  payload.len: %llu", rec->payload_len);
226 		if (rec->payload_len)
227 			zev_print_mark_payload(rec);
228 		znl();
229 	} else {
230 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
231 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
232 		       rec->mark_id, rec->payload_len);
233 	}
234 }
235 
236 static void
237 zev_print_zfs_mount(char *buf)
238 {
239 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
240 	time_t op_time = rec->op_time;
241 	char *ct = ctime(&op_time); ct[24] = '\0';
242 
243 	if (verbose) {
244 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
245 		zpf("  guid: %llu", rec->guid);
246 		zpf("  dataset: %s", ZEV_DATASET(rec));
247 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
248 		zpf("  remount: %s", rec->remount ? "true" : "false");
249 		zev_print_inode_info("root", &rec->root);
250 		znl();
251 	} else {
252 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
253 		       "mountpoint='%s'\n",
254 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
255 		       rec->guid,
256 		       rec->remount ? "true" : "false",
257 		       ZEV_DATASET(rec),
258 		       ZEV_MOUNTPOINT(rec));
259 	}
260 }
261 
262 static void
263 zev_print_zfs_umount(char *buf)
264 {
265 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
266 	time_t op_time = rec->op_time;
267 	char *ct = ctime(&op_time); ct[24] = '\0';
268 
269 	if (verbose) {
270 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
271 		zpf("  guid: %llu", rec->guid);
272 		znl();
273 	} else {
274 		printf("%s %s: guid=%llu\n",
275 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
276 		       rec->guid);
277 	}
278 }
279 
280 static void
281 zev_print_zvol_truncate(char *buf)
282 {
283 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
284 	time_t op_time = rec->op_time;
285 	char *ct = ctime(&op_time); ct[24] = '\0';
286 
287 	if (verbose) {
288 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
289 		zpf("  guid: %llu", rec->guid);
290 		zpf("  txg: %llu", rec->txg);
291 		zpf("  offset: %llu", rec->offset);
292 		zpf("  length: %llu", rec->length);
293 		znl();
294 	} else {
295 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
296 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
297 		       rec->guid,
298 		       rec->offset,
299 		       rec->length);
300 	}
301 }
302 
303 static void
304 zev_print_zvol_write(char *buf)
305 {
306 	zev_print_zvol_truncate(buf);
307 }
308 
309 static void
310 zev_print_znode_close_after_update(char *buf)
311 {
312 	zev_znode_close_after_update_t *rec =
313 	    (zev_znode_close_after_update_t *)buf;
314 	time_t op_time = rec->op_time;
315 	char *ct = ctime(&op_time); ct[24] = '\0';
316 
317 	if (verbose) {
318 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
319 		zpf("  guid: %llu", rec->guid);
320 		zev_print_inode_info("file", &rec->file);
321 		znl();
322 	} else {
323 		printf("%s %s: guid=%llu file=%llu.%llu\n",
324 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
325 		       rec->guid,
326 		       rec->file.ino, rec->file.gen);
327 	}
328 }
329 
330 static void
331 zev_print_znode_create(char *buf)
332 {
333 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
334 	time_t op_time = rec->op_time;
335 	char *ct = ctime(&op_time); ct[24] = '\0';
336 	zev_sig_t *sig;
337 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
338 
339 	if (verbose) {
340 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
341 		zpf("  guid: %llu", rec->guid);
342 		zpf("  txg: %llu", rec->txg);
343 		zpf("  name: '%s'", ZEV_NAME(rec));
344 		sig = &rec->signature;
345 		sig2hex_direct(sig->value, sigval);
346 		zpf("  sig: level %d, offset %llu, value %s",
347 		    sig->level, sig->block_offset, sigval);
348 		zev_print_inode_info("file", &rec->file);
349 		zev_print_inode_info("parent", &rec->parent);
350 		znl();
351 	} else {
352 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
353 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
354 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
355 		       rec->guid,
356 		       rec->parent.ino, rec->parent.gen,
357 		       rec->file.ino, rec->file.gen,
358 		       rec->file.mtime, rec->parent.mtime,
359 		       ZEV_NAME(rec));
360 	}
361 }
362 
363 static void
364 zev_print_znode_mkdir(char *buf)
365 {
366 	zev_print_znode_create(buf);
367 }
368 
369 static void
370 zev_print_znode_make_xattr_dir(char *buf)
371 {
372 	zev_print_znode_create(buf);
373 }
374 
375 static void
376 zev_print_znode_remove(char *buf)
377 {
378 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
379 	time_t op_time = rec->op_time;
380 	char *ct = ctime(&op_time); ct[24] = '\0';
381 
382 	if (verbose) {
383 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
384 		zpf("  guid: %llu", rec->guid);
385 		zpf("  txg: %llu", rec->txg);
386 		zpf("  file.name: '%s'", ZEV_NAME(rec));
387 		zev_print_inode_info("file", &rec->file);
388 		zev_print_inode_info("parent", &rec->parent);
389 		znl();
390 	} else {
391 		printf("%s %s: guid=%llu parent=%llu.%llu "
392 		       "file.mtime=%llu name='%s'\n",
393 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
394 		       rec->guid,
395 		       rec->parent.ino, rec->parent.gen,
396 		       rec->file.mtime,
397 		       ZEV_NAME(rec));
398 	}
399 }
400 
401 static void
402 zev_print_znode_rmdir(char *buf)
403 {
404 	zev_print_znode_remove(buf);
405 }
406 
407 static void
408 zev_print_znode_link(char *buf)
409 {
410 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
411 	time_t op_time = rec->op_time;
412 	char *ct = ctime(&op_time); ct[24] = '\0';
413 
414 	if (verbose) {
415 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
416 		zpf("  guid: %llu", rec->guid);
417 		zpf("  txg: %llu", rec->txg);
418 		zpf("  link.name: '%s'", ZEV_NAME(rec));
419 		zev_print_inode_info("file", &rec->file);
420 		zev_print_inode_info("parent", &rec->parent);
421 		znl();
422 	} else {
423 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
424 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
425 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
426 		       rec->parent.ino, rec->parent.gen,
427 		       rec->file.ino, rec->file.gen,
428 		       rec->file.ctime, rec->parent.ctime,
429 		       ZEV_NAME(rec));
430 	}
431 }
432 
433 static void
434 zev_print_znode_symlink(char *buf)
435 {
436 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
437 	time_t op_time = rec->op_time;
438 	char *ct = ctime(&op_time); ct[24] = '\0';
439 	zev_sig_t *sig;
440 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
441 
442 	if (verbose) {
443 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
444 		zpf("  guid: %llu", rec->guid);
445 		zpf("  txg: %llu", rec->txg);
446 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
447 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
448 		sig = &rec->signature;
449 		sig2hex_direct(sig->value, sigval);
450 		zpf("  sig: level %d, offset %llu, value %s",
451 		    sig->level, sig->block_offset, sigval);
452 		zev_print_inode_info("file", &rec->file);
453 		zev_print_inode_info("parent", &rec->parent);
454 		znl();
455 	} else {
456 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
457 		       "name='%s' link='%s'\n",
458 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
459 		       rec->parent.ino, rec->parent.gen,
460 		       rec->file.ino, rec->file.gen,
461 		       ZEV_NAME(rec),
462 		       ZEV_LINK(rec));
463 	}
464 }
465 
466 static void
467 zev_print_znode_rename(char *buf)
468 {
469 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
470 	time_t op_time = rec->op_time;
471 	char *ct = ctime(&op_time); ct[24] = '\0';
472 
473 	if (verbose) {
474 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
475 		zpf("  guid: %llu", rec->guid);
476 		zpf("  txg: %llu", rec->txg);
477 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
478 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
479 		zev_print_inode_info("file", &rec->file);
480 		zev_print_inode_info("srcdir", &rec->srcdir);
481 		zev_print_inode_info("dstdir", &rec->dstdir);
482 		znl();
483 	} else {
484 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
485 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
486 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
487 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
488 		       "srcname='%s' dstname='%s'\n",
489 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
490 		       rec->srcdir.ino, rec->srcdir.gen,
491 		       rec->dstdir.ino, rec->dstdir.gen,
492 		       rec->file.ino, rec->file.gen,
493 		       rec->file.mtime, rec->file.ctime,
494 		       rec->srcdir.mtime, rec->srcdir.ctime,
495 		       rec->dstdir.mtime, rec->dstdir.ctime,
496 		       ZEV_SRCNAME(rec),
497 		       ZEV_DSTNAME(rec));
498 	}
499 }
500 
501 static void
502 zev_print_znode_write(char *buf)
503 {
504 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
505 	time_t op_time = rec->op_time;
506 	char *ct = ctime(&op_time); ct[24] = '\0';
507 	zev_sig_t *sig;
508 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
509 	int i;
510 
511 	if (verbose) {
512 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
513 		zpf("  guid: %llu", rec->guid);
514 		zpf("  txg: %llu", rec->txg);
515 		zpf("  offset: %llu", rec->offset);
516 		zpf("  length: %llu", rec->length);
517 		zev_print_inode_info("file", &rec->file);
518 		znl();
519 		for (i=0; i<rec->signature_cnt; i++) {
520 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
521 			sig += i;
522 			sig2hex_direct(sig->value, sigval);
523 			zpf("  sig: level %d, offset %llu, value %s",
524 			    sig->level, sig->block_offset, sigval);
525 		}
526 	} else {
527 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
528 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
529 		       rec->file.ino, rec->file.gen,
530 		       rec->offset, rec->length);
531 	}
532 }
533 
534 static void
535 zev_print_znode_truncate(char *buf)
536 {
537 	zev_print_znode_write(buf);
538 }
539 
540 static void
541 zev_print_znode_setattr(char *buf)
542 {
543 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
544 	time_t op_time = rec->op_time;
545 	char *ct = ctime(&op_time); ct[24] = '\0';
546 
547 	if (verbose) {
548 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
549 		zpf("  guid: %llu", rec->guid);
550 		zpf("  txg: %llu", rec->txg);
551 		zev_print_inode_info("file", &rec->file);
552 		znl();
553 	} else {
554 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
555 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
556 		       rec->file.ino, rec->file.gen, rec->file.mtime);
557 	}
558 }
559 
560 static void
561 zev_print_znode_acl(char *buf)
562 {
563 	zev_print_znode_setattr(buf);
564 }
565 
566 static void
567 zev_print_event(char *buf, int len)
568 {
569 	int record_len;
570 	int op;
571 
572 	record_len = *(uint32_t *)buf;
573 	if (record_len != len) {
574 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
575 		        record_len, len);
576 		exit(1);
577 	}
578 	op = *((uint32_t *)buf + 1);
579 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
580 		fprintf(stderr, "unknown op code: %d\n", op);
581 		exit(1);
582 	}
583 	switch (op) {
584 	case ZEV_OP_ERROR:
585 		zev_print_error(buf);
586 		break;
587 	case ZEV_OP_MARK:
588 		zev_print_mark(buf);
589 		break;
590 	case ZEV_OP_ZFS_MOUNT:
591 		zev_print_zfs_mount(buf);
592 		break;
593 	case ZEV_OP_ZFS_UMOUNT:
594 		zev_print_zfs_umount(buf);
595 		break;
596 	case ZEV_OP_ZVOL_TRUNCATE:
597 		zev_print_zvol_truncate(buf);
598 		break;
599 	case ZEV_OP_ZVOL_WRITE:
600 		zev_print_zvol_write(buf);
601 		break;
602 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
603 		zev_print_znode_close_after_update(buf);
604 		break;
605 	case ZEV_OP_ZNODE_CREATE:
606 		zev_print_znode_create(buf);
607 		break;
608 	case ZEV_OP_ZNODE_MKDIR:
609 		zev_print_znode_mkdir(buf);
610 		break;
611 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
612 		zev_print_znode_make_xattr_dir(buf);
613 		break;
614 	case ZEV_OP_ZNODE_REMOVE:
615 		zev_print_znode_remove(buf);
616 		break;
617 	case ZEV_OP_ZNODE_RMDIR:
618 		zev_print_znode_rmdir(buf);
619 		break;
620 	case ZEV_OP_ZNODE_LINK:
621 		zev_print_znode_link(buf);
622 		break;
623 	case ZEV_OP_ZNODE_SYMLINK:
624 		zev_print_znode_symlink(buf);
625 		break;
626 	case ZEV_OP_ZNODE_RENAME:
627 		zev_print_znode_rename(buf);
628 		break;
629 	case ZEV_OP_ZNODE_WRITE:
630 		zev_print_znode_write(buf);
631 		break;
632 	case ZEV_OP_ZNODE_TRUNCATE:
633 		zev_print_znode_truncate(buf);
634 		break;
635 	case ZEV_OP_ZNODE_SETATTR:
636 		zev_print_znode_setattr(buf);
637 		break;
638 	case ZEV_OP_ZNODE_ACL:
639 		zev_print_znode_acl(buf);
640 		break;
641 	default:
642 		fprintf(stderr, "unhandled op code: %d\n", op);
643 		exit(1);
644 	}
645 }
646 
647 static int
648 zev_poll_events(int fd, int create_tmp_queue)
649 {
650 	struct pollfd pfd[1];
651 	int ret;
652 	char buf[4096];
653 	zev_event_t *ev;
654 	int off = 0;
655 	zev_ioctl_add_queue_t aq;
656 	int q_fd;
657 
658 	if (create_tmp_queue) {
659 		aq.zev_max_queue_len = 0;
660 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
661 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
662 			 "zevadm.%ld.%ld", time(NULL), getpid());
663 		aq.zev_namelen = strlen(aq.zev_name);
664 
665 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
666 			perror("adding temporary queue failed");
667 			return (EXIT_FAILURE);
668 		}
669 
670 		snprintf(buf, sizeof(buf),
671 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
672 		q_fd = open(buf, O_RDONLY);
673 		if (q_fd < 0) {
674 			perror("opening queue device failed");
675 			return (EXIT_FAILURE);
676 		}
677 	} else {
678 		q_fd = fd;
679 	}
680 
681 	while (1) {
682 		pfd[0].fd = q_fd;
683 		pfd[0].events = POLLIN;
684 		ret = poll(pfd, 1, 1000);
685 		if (ret < 0) {
686 			perror("poll failed");
687 			close(q_fd);
688 			return(EXIT_FAILURE);
689 		}
690 		if (!(pfd[0].revents & POLLIN))
691 			continue;
692 		/* data available */
693 		ret = read(q_fd, buf, sizeof(buf));
694 		if (ret < 0) {
695 			perror("read failed");
696 			close(q_fd);
697 			return(EXIT_FAILURE);
698 		}
699 		if (ret == 0)
700 			continue;
701 		while (ret > off) {
702 			ev = (zev_event_t *)(buf + off);
703 			zev_print_event(buf + off, ev->header.record_len);
704 			off += ev->header.record_len;
705 		}
706 		off = 0;
707 	}
708 	if (create_tmp_queue)
709 		close(q_fd);
710 	return EXIT_SUCCESS;
711 }
712 
713 static void
714 usage(char *progname)
715 {
716 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
717 	fprintf(stderr, "\n");
718 	fprintf(stderr, " Status information:\n");
719 	fprintf(stderr, "   -s                   show zev statistics\n");
720 	fprintf(stderr, "   -p                   poll for ZFS events\n");
721 	fprintf(stderr, "   -D                   print zev module debug "
722 	        "information\n");
723 	fprintf(stderr, "   -T <interval> <cnt>  zevstat mode\n");
724 	fprintf(stderr, "\n");
725 	fprintf(stderr, " Tune zev module settings:\n");
726 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
727 	        "length\n");
728 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
729 	        "this pool\n");
730 	fprintf(stderr, "   -M <pool>            unmute pool\n");
731 	fprintf(stderr, "\n");
732 	fprintf(stderr, " Queue management:\n");
733 	fprintf(stderr, "   -l                   list queues\n");
734 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
735 	fprintf(stderr, "   -A <name>            add blocking queue\n");
736 	fprintf(stderr, "   -r <name>            remove queue\n");
737 	fprintf(stderr, "   -b <name>            make queue non-blocking "
738 	        "(default)\n");
739 	fprintf(stderr, "   -B <name>            make queue block when full\n");
740 	fprintf(stderr, "   -P <name>            display queue properties\n");
741 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
742 	        "length\n");
743 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
744 	        "throttle\n");
745 	fprintf(stderr, "\n");
746 	fprintf(stderr, " Other options:\n");
747 	fprintf(stderr, "   -d <dev>             non-default device file. "
748 	        "('%s')\n", ZEV_DEVICE);
749 	fprintf(stderr, "   -q <name>            use device file for this "
750 		"queue name\n");
751 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
752 	fprintf(stderr, "   -c <filename>        list file's content "
753 		"checksums\n");
754 	fprintf(stderr, "   -v                   verbose: additional output "
755 	        "for some operations\n");
756 	fprintf(stderr, "   -g                   grep-friendly event output, "
757 	        "one event per line\n");
758 	exit (EXIT_FAILURE);
759 }
760 
761 static int
762 zev_add_queue(int fd, char *arg, int blocking)
763 {
764 	zev_ioctl_add_queue_t aq;
765 	int namelen;
766 
767 	namelen = strlen(arg);
768 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
769 		fprintf(stderr, "queue name too long: %s\n", arg);
770 		return (EXIT_FAILURE);
771 	}
772 
773 	aq.zev_namelen = namelen;
774 	strcpy(aq.zev_name, arg);
775 	aq.zev_flags = ZEV_FL_PERSISTENT;
776 	if (blocking) {
777 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
778 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
779 	} else {
780 		aq.zev_max_queue_len = (1024 * 1024);
781 	}
782 
783 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
784 		perror("adding queue failed");
785 		return (EXIT_FAILURE);
786 	}
787 	return (0);
788 }
789 
790 static int
791 zev_remove_queue(int fd, char *arg)
792 {
793 	zev_ioctl_remove_queue_t aq;
794 	int namelen;
795 
796 	namelen = strlen(arg);
797 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
798 		fprintf(stderr, "queue name too long: %s\n", arg);
799 		return (EXIT_FAILURE);
800 	}
801 
802 	aq.zev_queue_name.zev_namelen = namelen;
803 	strcpy(aq.zev_queue_name.zev_name, arg);
804 
805 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
806 		perror("removing queue failed");
807 		return (EXIT_FAILURE);
808 	}
809 	return (0);
810 }
811 
812 static int
813 zev_set_global_max_queue_len(int fd, char *arg)
814 {
815 	uint64_t maxqueuelen;
816 
817 	errno = 0;
818 	maxqueuelen = strtol(arg, (char **)NULL, 10);
819 	if (errno) {
820 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
821 		return (EXIT_FAILURE);
822 	}
823 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
824 		perror("setting max queue length failed");
825 		return (EXIT_FAILURE);
826 	}
827 	return (0);
828 }
829 
830 static int
831 zev_mute_unmute_impl(int fd, char *poolname, int mute)
832 {
833 	zev_ioctl_poolarg_t pa;
834 	int len;
835 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
836 	len = strlen(poolname);
837 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
838 		fprintf(stderr, "invalid poolname: %s\n", poolname);
839 		return (EXIT_FAILURE);
840 	}
841 	strcpy(pa.zev_poolname, poolname);
842 	pa.zev_poolname_len = len;
843 	if (ioctl(fd, op, &pa)) {
844 		perror("muting pool data failed");
845 		return (EXIT_FAILURE);
846 	}
847 	return (0);
848 }
849 
850 int
851 zev_mute_pool(int fd, char *poolname)
852 {
853 	return zev_mute_unmute_impl(fd, poolname, 1);
854 }
855 
856 int
857 zev_unmute_pool(int fd, char *poolname)
858 {
859 	return zev_mute_unmute_impl(fd, poolname, 0);
860 }
861 
862 static int
863 zev_debug_info(int fd)
864 {
865 	zev_ioctl_debug_info_t di;
866 
867 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
868 		perror("getting zev debug info failed");
869 		return (EXIT_FAILURE);
870 	}
871 
872 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
873 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
874 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
875 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
876 	return 0;
877 }
878 
879 static int
880 zev_mark(int fd, char *arg)
881 {
882 	zev_ioctl_mark_t *mark;
883 	uint64_t guid;
884 	int len;
885 	char *p;
886 
887 	p = strchr(arg, ':');
888 	if (!p) {
889 		fprintf(stderr, "expected value is <guid>:<payload>, "
890 		        "e.g. '123:hello'\n");
891 		exit (EXIT_FAILURE);
892 	}
893 	*p = '\n';
894 	p++;
895 
896 	errno = 0;
897 	guid = strtoll(arg, (char **)NULL, 10);
898 	if (errno) {
899 		fprintf(stderr, "guid must be a number.\n");
900 		exit (EXIT_FAILURE);
901 	}
902 
903 	len = strlen(p);
904 
905 	mark = malloc(sizeof(*mark) + len + 1);
906 	if (!mark) {
907 		fprintf(stderr, "can't allocate mark structure: %s\n",
908 		        strerror(errno));
909 		exit (EXIT_FAILURE);
910 	}
911 	mark->zev_guid = guid;
912 	mark->zev_mark_id = 0;
913 	mark->zev_payload_len = len;
914 	strcpy(ZEV_PAYLOAD(mark), p);
915 
916 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
917 		perror("queueing mark failed");
918 		return (EXIT_FAILURE);
919 	}
920 
921 	printf("mark id: %lu\n", mark->zev_mark_id);
922 	return (0);
923 }
924 
925 static int
926 zev_queue_blocking(int fd, char *arg, int block)
927 {
928 	zev_ioctl_get_queue_properties_t gqp;
929 
930 	gqp.zev_queue_name.zev_namelen = strlen(arg);
931 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
932 		fprintf(stderr, "queue name too long.\n");
933 		return EXIT_FAILURE;
934 	}
935 	strcpy(gqp.zev_queue_name.zev_name, arg);
936 
937 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
938 		perror("getting queue properties failed");
939 		return (EXIT_FAILURE);
940 	}
941 	if (block) {
942 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
943 	} else {
944 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
945 	}
946 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
947 		perror("setting queue properties failed");
948 		return (EXIT_FAILURE);
949 	}
950 	return (0);
951 }
952 
953 static int
954 zev_set_max_queue_len(int fd, char *arg, char *len)
955 {
956 	zev_ioctl_get_queue_properties_t gqp;
957 
958 	if (!len) {
959 		fprintf(stderr, "queue size parameter missing.\n");
960 		return EXIT_FAILURE;
961 	}
962 
963 	gqp.zev_queue_name.zev_namelen = strlen(arg);
964 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
965 		fprintf(stderr, "queue name too long.\n");
966 		return EXIT_FAILURE;
967 	}
968 	strcpy(gqp.zev_queue_name.zev_name, arg);
969 
970 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
971 		perror("getting queue properties failed");
972 		return (EXIT_FAILURE);
973 	}
974 	gqp.zev_max_queue_len = atol(len);
975 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
976 		fprintf(stderr, "queue size parameter garbled.\n");
977 		return (EXIT_FAILURE);
978 	}
979 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
980 		fprintf(stderr, "queue size parameter out of bounds.\n");
981 		return (EXIT_FAILURE);
982 	}
983 
984 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
985 		perror("setting queue properties failed");
986 		return (EXIT_FAILURE);
987 	}
988 	return (0);
989 }
990 
991 static int
992 zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
993 {
994 	zev_ioctl_get_queue_properties_t gqp;
995 
996 	if (!len) {
997 		fprintf(stderr, "poll throttle parameter missing.\n");
998 		return EXIT_FAILURE;
999 	}
1000 
1001 	gqp.zev_queue_name.zev_namelen = strlen(arg);
1002 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1003 		fprintf(stderr, "queue name too long.\n");
1004 		return EXIT_FAILURE;
1005 	}
1006 	strcpy(gqp.zev_queue_name.zev_name, arg);
1007 
1008 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1009 		perror("getting queue properties failed");
1010 		return (EXIT_FAILURE);
1011 	}
1012 	gqp.zev_poll_wakeup_threshold = atol(len);
1013 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
1014 		fprintf(stderr, "poll throttle parameter garbled.\n");
1015 		return (EXIT_FAILURE);
1016 	}
1017 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
1018 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
1019 		return (EXIT_FAILURE);
1020 	}
1021 
1022 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1023 		perror("setting queue properties failed");
1024 		return (EXIT_FAILURE);
1025 	}
1026 	return (0);
1027 }
1028 
1029 static int
1030 zev_queue_properties(int fd, char *arg)
1031 {
1032 	zev_ioctl_get_queue_properties_t gqp;
1033 
1034 	gqp.zev_queue_name.zev_namelen = strlen(arg);
1035 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1036 		fprintf(stderr, "queue name too long.\n");
1037 		return EXIT_FAILURE;
1038 	}
1039 	strcpy(gqp.zev_queue_name.zev_name, arg);
1040 
1041 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1042 		perror("getting queue properties failed");
1043 		return (EXIT_FAILURE);
1044 	}
1045 
1046 	printf("queue        : %s\n", arg);
1047 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1048 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1049 	printf("persistent   : %s\n",
1050 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1051 	printf("blocking     : %s\n",
1052 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1053 
1054 	return (0);
1055 }
1056 
1057 static int
1058 zev_list_queues(int fd)
1059 {
1060 	zev_ioctl_get_queue_properties_t gqp;
1061 	zev_ioctl_get_queue_list_t gql;
1062 	zev_ioctl_get_queue_statistics_t gs;
1063 	uint64_t	i;
1064 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1065 
1066 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1067 		perror("getting queue list failed");
1068 		return (EXIT_FAILURE);
1069 	}
1070 
1071 	printf("Name                                     Size       "
1072 	       "Max Size   Wakeup Per Block\n");
1073 
1074 	for (i=0; i<gql.zev_n_queues; i++) {
1075 		strncpy(name, gql.zev_queue_name[i].zev_name,
1076 		        ZEV_MAX_QUEUE_NAME_LEN);
1077 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1078 
1079 		memcpy(gqp.zev_queue_name.zev_name,
1080 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
1081 		gqp.zev_queue_name.zev_namelen =
1082 		    gql.zev_queue_name[i].zev_namelen;
1083 
1084 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1085 			if (errno == ENOENT)
1086 				continue;
1087 			perror("getting queue properties failed");
1088 			return (EXIT_FAILURE);
1089 		}
1090 
1091 		memcpy(gs.zev_queue_name.zev_name,
1092 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
1093 		gs.zev_queue_name.zev_namelen =
1094 		    gql.zev_queue_name[i].zev_namelen;
1095 
1096 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1097 			if (errno == ENOENT)
1098 				continue;
1099 			perror("getting statistics data failed");
1100 			return (EXIT_FAILURE);
1101 		}
1102 
1103 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
1104 		       " %-3s %-3s\n",
1105 			name,
1106 			gs.zev_statistics.zev_queue_len,
1107 			gqp.zev_max_queue_len,
1108 			gqp.zev_poll_wakeup_threshold,
1109 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1110 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1111 				 "yes" : "no");
1112 	}
1113 
1114 	return (0);
1115 }
1116 
1117 static int
1118 zev_checksum(int dev_fd, char *filename)
1119 {
1120 	int fd;
1121 	offset_t off;
1122 	offset_t data;
1123 	zev_sig_t *sig;
1124 	char *buf;
1125 	zev_ioctl_get_signatures_t *gs;
1126 	int i;
1127 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
1128 	int buf_size;
1129 
1130 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
1131 	buf_size = (1 + 256) * sizeof(zev_sig_t);
1132 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
1133 	if (!buf) {
1134 		perror("can't allocate checksum buffer");
1135 		return (EXIT_FAILURE);
1136 	}
1137 
1138 	fd = open(filename, O_RDONLY);
1139 	if (fd < 0) {
1140 		perror("can't open file");
1141 		return (EXIT_FAILURE);
1142 	}
1143 
1144 	gs = (zev_ioctl_get_signatures_t *)buf;
1145 	gs->zev_fd = fd;
1146 	gs->zev_bufsize = buf_size;
1147 
1148 	off = 0;
1149 	data = 0;
1150 	while (1) {
1151 		errno = 0;
1152 		data = llseek(fd, off, SEEK_DATA);
1153 		if (data < 0) {
1154 			if (errno == ENXIO)	/* no more data */
1155 				break;
1156 			perror("llseek failed");
1157 			goto err;
1158 		}
1159 		data = P2ALIGN(data, ZEV_L1_SIZE);
1160 		off = data + ZEV_L1_SIZE;
1161 
1162 		gs->zev_offset = data;
1163 		gs->zev_len = ZEV_L1_SIZE;
1164 
1165 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
1166 			perror("ioctl to get signatures failed");
1167 			goto err;
1168 		}
1169 
1170 		for (i=0; i<gs->zev_signature_cnt; i++) {
1171 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
1172 			sig += i;
1173 			sig2hex_direct(sig->value, sigval);
1174 			printf("level %d, offset %llu, value %s\n",
1175 			       sig->level, sig->block_offset, sigval);
1176 		}
1177 	}
1178 
1179 	free(buf);
1180 	close(fd);
1181 	return 0;
1182 err:
1183 	free(buf);
1184 	close(fd);
1185 	return (EXIT_FAILURE);
1186 }
1187 
1188 typedef struct zevstat {
1189 	uint64_t	ns_start;
1190 	uint64_t	events[ZEV_OP_MIN + ZEV_OP_MAX];
1191 	uint64_t	guids;
1192 	uint64_t	total_events;
1193 	uint64_t	total_guids;
1194 	avl_tree_t	guids_interval;
1195 	avl_tree_t	guids_runtime;
1196 } zevstat_t;
1197 
1198 typedef struct zev_guidtrack_t {
1199 	uint64_t	guid;
1200 	avl_node_t	avl_interval;
1201 	avl_node_t	avl_runtime;
1202 } zev_guidtrack_t;
1203 
1204 zevstat_t zevstat;
1205 
1206 static void
1207 zev_eventstat(char *buf, int len)
1208 {
1209 	zev_header_t *rec = (zev_header_t *)buf;
1210 	zev_guidtrack_t *gt;
1211 	zev_guidtrack_t *gt_int;
1212 	zev_guidtrack_t to_find;
1213 	avl_index_t where;
1214 
1215 	zevstat.total_events++;
1216 	zevstat.events[rec->op]++;
1217 
1218 	to_find.guid = rec->guid;
1219 	gt = avl_find(&zevstat.guids_runtime, &to_find, &where);
1220 	if (!gt) {
1221 		gt = malloc(sizeof(*gt));
1222 		if (!gt) {
1223 			perror("can't get guid tracking record");
1224 			exit (EXIT_FAILURE);
1225 		}
1226 		gt->guid = rec->guid;
1227 		avl_insert(&zevstat.guids_runtime, gt, where);
1228 	}
1229 	gt_int = avl_find(&zevstat.guids_interval, &to_find, &where);
1230 	if (!gt_int)
1231 		avl_insert(&zevstat.guids_interval, gt, where);
1232 }
1233 
1234 static void
1235 zev_eventstat_interval(void)
1236 {
1237 	uint64_t events;
1238 	int i;
1239 	zev_guidtrack_t *gt;
1240 
1241 	events = 0;
1242 	for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) {
1243 		events += zevstat.events[i];
1244 	}
1245 
1246 	if (verbose) {
1247 		printf("%u  %6llu  %6llu %6llu %6llu  ",
1248 		       time(NULL),
1249 		       events,
1250 		       zevstat.total_events,
1251 		       avl_numnodes(&zevstat.guids_interval),
1252 		       avl_numnodes(&zevstat.guids_runtime));
1253 		for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++)
1254 			printf("%6llu ", zevstat.events[i]);
1255 		printf("\n");
1256 	} else {
1257 		printf("%u  %6llu  %6llu %6llu %6llu\n",
1258 		       time(NULL),
1259 		       events,
1260 		       zevstat.total_events,
1261 		       avl_numnodes(&zevstat.guids_interval),
1262 		       avl_numnodes(&zevstat.guids_runtime));
1263 	}
1264 	memset(&zevstat.events, 0, sizeof(zevstat.events));
1265 	zevstat.guids = 0;
1266 	while (gt = avl_first(&zevstat.guids_interval))
1267 		avl_remove(&zevstat.guids_interval, gt);
1268 }
1269 
1270 static int
1271 zev_evcompar(const void *a, const void *b)
1272 {
1273 	const zev_guidtrack_t *ga = a;
1274 	const zev_guidtrack_t *gb = b;
1275 
1276 	if (ga->guid > gb->guid)
1277 		return 1;
1278 	if (ga->guid < gb->guid)
1279 		return -1;
1280 	return 0;
1281 }
1282 
1283 static int
1284 zev_zevstat(int fd, char *s_interval, char *s_count)
1285 {
1286 	uint64_t interval = 1000;
1287 	uint64_t ms;
1288 	uint64_t t_until;
1289 	uint64_t t_now;
1290 	int cnt = -1;
1291 	struct pollfd pfd[1];
1292 	int ret;
1293 	char buf[4096];
1294 	zev_event_t *ev;
1295 	int off = 0;
1296 	zev_ioctl_add_queue_t aq;
1297 	int q_fd;
1298 	zev_guidtrack_t *gt;
1299 
1300 	memset(&zevstat, 0, sizeof(zevstat));
1301 	avl_create(&zevstat.guids_runtime, zev_evcompar,
1302 	           sizeof(zev_guidtrack_t),
1303 	           offsetof(zev_guidtrack_t, avl_runtime));
1304 	avl_create(&zevstat.guids_interval, zev_evcompar,
1305 	           sizeof(zev_guidtrack_t),
1306 	           offsetof(zev_guidtrack_t, avl_interval));
1307 
1308 	interval = atol(s_interval);
1309 	if (interval == 0) {
1310 		fprintf(stderr, "invalid interval.\n");
1311 		return (EXIT_FAILURE);
1312 	}
1313 	interval *= 1000;
1314 	if (s_count) {
1315 		cnt = atol(s_count);
1316 		if (interval == 0) {
1317 			fprintf(stderr, "invalid count.\n");
1318 			return (EXIT_FAILURE);
1319 		}
1320 	}
1321 
1322 	aq.zev_max_queue_len = 1024 * 1024;
1323 	aq.zev_flags = 0;
1324 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
1325 		 "zevstat.%ld.%ld", time(NULL), getpid());
1326 	aq.zev_namelen = strlen(aq.zev_name);
1327 
1328 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
1329 		perror("adding temporary queue failed");
1330 		return (EXIT_FAILURE);
1331 	}
1332 
1333 	snprintf(buf, sizeof(buf),
1334 		 "/devices/pseudo/zev@0:%s", aq.zev_name);
1335 	q_fd = open(buf, O_RDONLY);
1336 	if (q_fd < 0) {
1337 		perror("opening queue device failed");
1338 		return (EXIT_FAILURE);
1339 	}
1340 
1341 	pfd[0].fd = q_fd;
1342 	pfd[0].events = POLLIN;
1343 
1344 	/* drain queue */
1345 	while ((ret = poll(pfd, 1, 1000)) > 0) {
1346 		if (read(q_fd, buf, sizeof(buf)) < 0) {
1347 			perror("read failed");
1348 			close(q_fd);
1349 			return(EXIT_FAILURE);
1350 		}
1351 	}
1352 	if (ret < 0) {
1353 		perror("poll failed");
1354 		close(q_fd);
1355 		return(EXIT_FAILURE);
1356 	}
1357 
1358 	printf("timestamp   events tevents  guids tguids");
1359 	if (verbose) {
1360 		printf("   error   mark  mount umount zvol_w zvol_t ");
1361 		printf(" close create  mkdir mxattr remove  rmdir ");
1362 		printf("  link symlnk rename  write  trunc setatt    acl");
1363 	}
1364 	printf("\n");
1365 	while (cnt) {
1366 		t_until = gethrtime() + (interval * 1000000);
1367 		ms = interval;
1368 		do {
1369 			ret = poll(pfd, 1, ms);
1370 			t_now = gethrtime();
1371 			if (t_now < t_until) {
1372 				ms = t_until - t_now;
1373 				ms /= 1000000ull;
1374 			}
1375 			if (ret < 0) {
1376 				perror("poll failed");
1377 				close(q_fd);
1378 				return(EXIT_FAILURE);
1379 			}
1380 			if (!(pfd[0].revents & POLLIN))
1381 				continue;
1382 			/* data available */
1383 			ret = read(q_fd, buf, sizeof(buf));
1384 			if (ret < 0) {
1385 				perror("read failed");
1386 				close(q_fd);
1387 				return(EXIT_FAILURE);
1388 			}
1389 			if (ret == 0)
1390 				continue;
1391 			while (ret > off) {
1392 				ev = (zev_event_t *)(buf + off);
1393 				zev_eventstat(buf + off, ev->header.record_len);
1394 				off += ev->header.record_len;
1395 			}
1396 			off = 0;
1397 		} while ((t_now) < t_until && (ms > 0));
1398 		zev_eventstat_interval();
1399 		if (cnt > 0)
1400 			cnt--;
1401 	}
1402 	close(q_fd);
1403 	while (gt = avl_first(&zevstat.guids_interval))
1404 		avl_remove(&zevstat.guids_interval, gt);
1405 	while (gt = avl_first(&zevstat.guids_runtime)) {
1406 		avl_remove(&zevstat.guids_runtime, gt);
1407 		free(gt);
1408 	}
1409 	return EXIT_SUCCESS;
1410 }
1411 
1412 int
1413 main(int argc, char **argv)
1414 {
1415 	int fd;
1416 	int c;
1417 	extern char *optarg;
1418 	int create_tmp_queue = 1;
1419 	char buf[MAXPATHLEN];
1420 	int mode = 0;
1421 	char *arg = NULL;
1422 	char *arg2 = NULL;
1423 	char *p;
1424 
1425 	p = strrchr(argv[0], '/');
1426 	if (!p) {
1427 		p = argv[0];
1428 	} else {
1429 		p++;
1430 	}
1431 	if (!strcmp(p, "zevstat")) {
1432 		mode = MD_ZEVSTAT;
1433 	}
1434 
1435 	/* open device */
1436 	fd = open(zev_device, O_RDONLY);
1437 	if (fd < 0) {
1438 		perror("opening zev device failed");
1439 		return EXIT_FAILURE;
1440 	}
1441 	while ((c = getopt(argc, argv,
1442 	                   "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:T:h?")) != -1){
1443 		switch(c) {
1444 		case 'g':
1445 			grep_friendly++;
1446 			verbose++;
1447 			break;
1448 		case 'v':
1449 			verbose++;
1450 			break;
1451 		case 's':
1452 			mode = MD_STATISTICS;
1453 			break;
1454 		case 'p':
1455 			mode = MD_POLL_EVENTS;
1456 			break;
1457 		case 'c':
1458 			mode = MD_CHECKSUMS;
1459 			arg = optarg;
1460 			break;
1461 		case 'D':
1462 			mode = MD_DEBUG_INFO;
1463 			break;
1464 		case 'd':
1465 			close(fd);
1466 			zev_device = optarg;
1467 			fd = open(zev_device, O_RDONLY);
1468 			if (fd < 0) {
1469 				perror("opening zev device failed");
1470 				return EXIT_FAILURE;
1471 			}
1472 			create_tmp_queue = 0;
1473 			break;
1474 		case 'q':
1475 			snprintf(buf, sizeof(buf),
1476 				 "/devices/pseudo/zev@0:%s", optarg);
1477 			close(fd);
1478 			zev_device = buf;
1479 			fd = open(zev_device, O_RDONLY);
1480 			if (fd < 0) {
1481 				perror("opening zev device failed");
1482 				return EXIT_FAILURE;
1483 			}
1484 			create_tmp_queue = 0;
1485 			break;
1486 		case 'l':
1487 			mode = MD_LIST_QUEUES;
1488 			break;
1489 		case 'Q':
1490 			mode = MD_SET_GLOBAL_MAX_QUEUE_LEN;
1491 			arg = optarg;
1492 			break;
1493 		case 'L':
1494 			mode = MD_SET_MAX_QUEUE_LEN;
1495 			arg = optarg;
1496 			arg2 = argv[optind];
1497 			break;
1498 		case 'T':
1499 			mode = MD_ZEVSTAT;
1500 			arg = optarg;
1501 			arg2 = argv[optind];
1502 			break;
1503 		case 't':
1504 			mode = MD_SET_POLL_WAKEUP_QUEUE_LEN;
1505 			arg = optarg;
1506 			arg2 = argv[optind];
1507 			break;
1508 		case 'm':
1509 			mode = MD_MUTE_POOL;
1510 			arg = optarg;
1511 			break;
1512 		case 'M':
1513 			mode = MD_UNMUTE_POOL;
1514 			arg = optarg;
1515 			break;
1516 		case 'k':
1517 			mode = MD_MARK;
1518 			arg = optarg;
1519 			break;
1520 		case 'a':
1521 			mode = MD_ADD_QUEUE;
1522 			arg = optarg;
1523 			break;
1524 		case 'A':
1525 			mode = MD_ADD_BLOCKING_QUEUE;
1526 			arg = optarg;
1527 			break;
1528 		case 'r':
1529 			mode = MD_REMOVE_QUEUE;
1530 			arg = optarg;
1531 			break;
1532 		case 'b':
1533 			mode = MD_QUEUE_BLOCKING;
1534 			arg = optarg;
1535 			break;
1536 		case 'B':
1537 			mode = MD_QUEUE_NONBLOCKING;
1538 			arg = optarg;
1539 			break;
1540 		case 'P':
1541 			mode = MD_QUEUE_PROPERTIES;
1542 			arg = optarg;
1543 			break;
1544 		case 'h':
1545 		case '?':
1546 		default:
1547 			usage(argv[0]);
1548 		}
1549 	}
1550 
1551 	switch (mode) {
1552 	case MD_STATISTICS:
1553 		return zev_statistics(fd);
1554 	case MD_POLL_EVENTS:
1555 		return zev_poll_events(fd, create_tmp_queue);
1556 	case MD_CHECKSUMS:
1557 		return zev_checksum(fd, arg);
1558 	case MD_DEBUG_INFO:
1559 		return zev_debug_info(fd);
1560 	case MD_LIST_QUEUES:
1561 		return zev_list_queues(fd);
1562 	case MD_SET_GLOBAL_MAX_QUEUE_LEN:
1563 		return zev_set_global_max_queue_len(fd, arg);
1564 	case MD_SET_MAX_QUEUE_LEN:
1565 		return zev_set_max_queue_len(fd, arg, arg2);
1566 	case MD_SET_POLL_WAKEUP_QUEUE_LEN:
1567 		return zev_set_poll_wakeup_queue_len(fd, arg, arg2);
1568 	case MD_ZEVSTAT:
1569 		return zev_zevstat(fd, arg, arg2);
1570 	case MD_MUTE_POOL:
1571 		return zev_mute_pool(fd, arg);
1572 	case MD_UNMUTE_POOL:
1573 		return zev_unmute_pool(fd, arg);
1574 	case MD_MARK:
1575 		return zev_mark(fd, arg);
1576 	case MD_ADD_QUEUE:
1577 		return zev_add_queue(fd, arg, 0);
1578 	case MD_ADD_BLOCKING_QUEUE:
1579 		return zev_add_queue(fd, arg, 1);
1580 	case MD_REMOVE_QUEUE:
1581 		return zev_remove_queue(fd, arg);
1582 	case MD_QUEUE_BLOCKING:
1583 		return zev_queue_blocking(fd, arg, 0);
1584 	case MD_QUEUE_NONBLOCKING:
1585 		return zev_queue_blocking(fd, arg, 1);
1586 	case MD_QUEUE_PROPERTIES:
1587 		return zev_queue_properties(fd, arg);
1588 	default:
1589 		close(fd);
1590 		usage(argv[0]);
1591 		return EXIT_FAILURE;
1592 	};
1593 }
1594 
1595