xref: /titanic_51/usr/src/cmd/zevadm/zevadm.c (revision 29fab2f92696840d2cd7f5084bda35298e42f632)
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>
10b9710123SAndreas Jaekel #include <sys/sysmacros.h>
11d65b2fffSAndreas Jaekel #include <stdarg.h>
120abdde4aSAndreas Jaekel #include <sys/avl.h>
132bb8e5e2SAndreas Jaekel 
14e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
152bb8e5e2SAndreas Jaekel 
160abdde4aSAndreas Jaekel #if !defined(offsetof)
170abdde4aSAndreas Jaekel #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
180abdde4aSAndreas Jaekel #endif
190abdde4aSAndreas Jaekel 
202bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
212bb8e5e2SAndreas Jaekel 
229193e9c2SAndreas Jaekel static char *zev_op_name[] = {
23d65b2fffSAndreas Jaekel 	"ERROR",
24d65b2fffSAndreas Jaekel 	"MARK",
25d65b2fffSAndreas Jaekel 	"ZFS_MOUNT",
26d65b2fffSAndreas Jaekel 	"ZFS_UMOUNT",
27d65b2fffSAndreas Jaekel 	"ZVOL_WRITE",
28d65b2fffSAndreas Jaekel 	"ZVOL_TRUNCATE",
29d65b2fffSAndreas Jaekel 	"ZNODE_CLOSE_AFTER_UPDATE",
30d65b2fffSAndreas Jaekel 	"ZNODE_CREATE",
31d65b2fffSAndreas Jaekel 	"ZNODE_MKDIR",
32d65b2fffSAndreas Jaekel 	"ZNODE_MAKE_XATTR_DIR",
33d65b2fffSAndreas Jaekel 	"ZNODE_REMOVE",
34d65b2fffSAndreas Jaekel 	"ZNODE_RMDIR",
35d65b2fffSAndreas Jaekel 	"ZNODE_LINK",
36d65b2fffSAndreas Jaekel 	"ZNODE_SYMLINK",
37d65b2fffSAndreas Jaekel 	"ZNODE_RENAME",
38d65b2fffSAndreas Jaekel 	"ZNODE_WRITE",
39d65b2fffSAndreas Jaekel 	"ZNODE_TRUNCATE",
40d65b2fffSAndreas Jaekel 	"ZNODE_SETATTR",
41d65b2fffSAndreas Jaekel 	"ZNODE_ACL",
429193e9c2SAndreas Jaekel 	NULL
439193e9c2SAndreas Jaekel };
449193e9c2SAndreas Jaekel 
456a3d43bfSAndreas Jaekel #define MD_STATISTICS			1
466a3d43bfSAndreas Jaekel #define MD_POLL_EVENTS			2
476a3d43bfSAndreas Jaekel #define MD_CHECKSUMS			3
486a3d43bfSAndreas Jaekel #define MD_DEBUG_INFO			4
496a3d43bfSAndreas Jaekel #define MD_LIST_QUEUES			5
506a3d43bfSAndreas Jaekel #define MD_SET_GLOBAL_MAX_QUEUE_LEN	6
516a3d43bfSAndreas Jaekel #define MD_SET_MAX_QUEUE_LEN		7
526a3d43bfSAndreas Jaekel #define MD_SET_POLL_WAKEUP_QUEUE_LEN	8
536a3d43bfSAndreas Jaekel #define MD_MUTE_POOL			9
546a3d43bfSAndreas Jaekel #define MD_UNMUTE_POOL			10
556a3d43bfSAndreas Jaekel #define MD_MARK				11
566a3d43bfSAndreas Jaekel #define MD_ADD_QUEUE			12
576a3d43bfSAndreas Jaekel #define MD_ADD_BLOCKING_QUEUE		13
586a3d43bfSAndreas Jaekel #define MD_REMOVE_QUEUE			14
596a3d43bfSAndreas Jaekel #define MD_QUEUE_BLOCKING		15
606a3d43bfSAndreas Jaekel #define MD_QUEUE_NONBLOCKING		16
616a3d43bfSAndreas Jaekel #define MD_QUEUE_PROPERTIES		17
620abdde4aSAndreas Jaekel #define MD_ZEVSTAT			18
636a3d43bfSAndreas Jaekel 
645e286361SAndreas Jaekel static int verbose = 0;
65d65b2fffSAndreas Jaekel static int grep_friendly = 0;
66d65b2fffSAndreas Jaekel 
67d65b2fffSAndreas Jaekel static void
68d65b2fffSAndreas Jaekel zpf(char *fmt, ...)
69d65b2fffSAndreas Jaekel {
70d65b2fffSAndreas Jaekel 	va_list	ap;
71d65b2fffSAndreas Jaekel 
72d65b2fffSAndreas Jaekel 	va_start(ap, fmt);
73d65b2fffSAndreas Jaekel 	vprintf(fmt, ap);
74d65b2fffSAndreas Jaekel 	va_end(ap);
75d65b2fffSAndreas Jaekel 	if (grep_friendly) {
76d65b2fffSAndreas Jaekel 		printf(" ");
77d65b2fffSAndreas Jaekel 	} else {
78d65b2fffSAndreas Jaekel 		printf("\n");
79d65b2fffSAndreas Jaekel 	}
80d65b2fffSAndreas Jaekel }
81d65b2fffSAndreas Jaekel 
82d65b2fffSAndreas Jaekel static void
83d65b2fffSAndreas Jaekel znl(void)
84d65b2fffSAndreas Jaekel {
85d65b2fffSAndreas Jaekel 	if (grep_friendly)
86d65b2fffSAndreas Jaekel 		printf("\n");
87d65b2fffSAndreas Jaekel }
885e286361SAndreas Jaekel 
891ca5a13bSAndreas Jaekel static void
901ca5a13bSAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
911ca5a13bSAndreas Jaekel {
921ca5a13bSAndreas Jaekel 	int     i;
931ca5a13bSAndreas Jaekel 
941ca5a13bSAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
951ca5a13bSAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
961ca5a13bSAndreas Jaekel 	}
971ca5a13bSAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
981ca5a13bSAndreas Jaekel }
991ca5a13bSAndreas Jaekel 
100e9a5e479SAndreas Jaekel static int
1012bb8e5e2SAndreas Jaekel zev_statistics(int fd)
1022bb8e5e2SAndreas Jaekel {
1032bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
104e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
1052bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
106e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1072bb8e5e2SAndreas Jaekel 	}
1082bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
1092bb8e5e2SAndreas Jaekel 
1102bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
1112bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
1122bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
1132bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
1142bb8e5e2SAndreas Jaekel 
115e9a5e479SAndreas Jaekel 	printf("    discarded events        : %lu\n",
116e9a5e479SAndreas Jaekel 	    zs.zev_cnt_discarded_events);
117e9a5e479SAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
118e9a5e479SAndreas Jaekel 
1192bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
1202bb8e5e2SAndreas Jaekel 
1212bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
1222bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
1232bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
1242bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
1252bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
1262bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
1272bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
1282bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
1292bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
1302bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
1312bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
1322bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
1332bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
1342bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
1352bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
1362bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
1372bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
138e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
1392bb8e5e2SAndreas Jaekel }
1402bb8e5e2SAndreas Jaekel 
1412bb8e5e2SAndreas Jaekel static void
142d65b2fffSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info)
143d65b2fffSAndreas Jaekel {
144d65b2fffSAndreas Jaekel 	zpf("  %s.inode: %llu", name, info->ino);
145d65b2fffSAndreas Jaekel 	zpf("  %s.gen: %llu", name, info->gen);
146d65b2fffSAndreas Jaekel 	zpf("  %s.mtime: %llu", name, info->mtime);
147d65b2fffSAndreas Jaekel 	zpf("  %s.ctime: %llu", name, info->ctime);
148d65b2fffSAndreas Jaekel 	zpf("  %s.size: %llu", name, info->size);
149d65b2fffSAndreas Jaekel 	zpf("  %s.mode: %llo", name, info->mode);
150d65b2fffSAndreas Jaekel 	zpf("  %s.links: %llu", name, info->links);
151d65b2fffSAndreas Jaekel 	zpf("  %s.type: %lu", name, info->type);
152d65b2fffSAndreas Jaekel 	zpf("  %s.flags: %lu", name, info->flags);
153d65b2fffSAndreas Jaekel }
154d65b2fffSAndreas Jaekel 
155d65b2fffSAndreas Jaekel static void
156d65b2fffSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec)
157d65b2fffSAndreas Jaekel {
158d65b2fffSAndreas Jaekel 	int i;
159d65b2fffSAndreas Jaekel 	int j;
160d65b2fffSAndreas Jaekel 	uint8_t *p;
161d65b2fffSAndreas Jaekel 	char c;
162d65b2fffSAndreas Jaekel 
163d65b2fffSAndreas Jaekel 	zpf("  payload:");
164d65b2fffSAndreas Jaekel 	p = (uint8_t *)ZEV_PAYLOAD(rec);
165d65b2fffSAndreas Jaekel 	for (i=0; i<rec->payload_len; i+=16) {
166d65b2fffSAndreas Jaekel 		printf("  ");
167d65b2fffSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
168d65b2fffSAndreas Jaekel 			printf("%02x ", p[j]);
169d65b2fffSAndreas Jaekel 			if (j == i + 7)
170d65b2fffSAndreas Jaekel 				printf(" ");
171d65b2fffSAndreas Jaekel 		}
172d65b2fffSAndreas Jaekel 		if (grep_friendly)
173d65b2fffSAndreas Jaekel 			continue;
174d65b2fffSAndreas Jaekel 		for (; j<i+16; j++) {
175d65b2fffSAndreas Jaekel 			printf("   ");
176d65b2fffSAndreas Jaekel 			if (j == i + 7)
177d65b2fffSAndreas Jaekel 				printf(" ");
178d65b2fffSAndreas Jaekel 		}
179d65b2fffSAndreas Jaekel 		printf("    ");
180d65b2fffSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
181d65b2fffSAndreas Jaekel 			c = '.';
182d65b2fffSAndreas Jaekel 			if (p[j] >= ' ' && p[j] <= '~')
183d65b2fffSAndreas Jaekel 				c = p[j];
184d65b2fffSAndreas Jaekel 			printf("%c", c);
185d65b2fffSAndreas Jaekel 			if (j == i + 7)
186d65b2fffSAndreas Jaekel 				printf(" ");
187d65b2fffSAndreas Jaekel 		}
188d65b2fffSAndreas Jaekel 		printf("\n");
189d65b2fffSAndreas Jaekel 	}
190d65b2fffSAndreas Jaekel }
191d65b2fffSAndreas Jaekel 
192d65b2fffSAndreas Jaekel static void
19363aba447SAndreas Jaekel zev_print_error(char *buf)
19463aba447SAndreas Jaekel {
19563aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
19663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
19763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
19863aba447SAndreas Jaekel 
199d65b2fffSAndreas Jaekel 	if (verbose) {
200d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
201d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
202d65b2fffSAndreas Jaekel 		zpf("  failed.op: %s",
203d65b2fffSAndreas Jaekel 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
204d65b2fffSAndreas Jaekel 		zpf("  message: %s", ZEV_ERRSTR(rec));
205d65b2fffSAndreas Jaekel 		znl();
206d65b2fffSAndreas Jaekel 	} else {
20763aba447SAndreas Jaekel 		printf("%s %s: failed_op=%s msg=%s\n",
20863aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
209d65b2fffSAndreas Jaekel 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
210d65b2fffSAndreas Jaekel 		       ZEV_ERRSTR(rec));
211d65b2fffSAndreas Jaekel 	}
21263aba447SAndreas Jaekel }
21363aba447SAndreas Jaekel 
21463aba447SAndreas Jaekel static void
21501c2c787SAndreas Jaekel zev_print_mark(char *buf)
21601c2c787SAndreas Jaekel {
21701c2c787SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
21801c2c787SAndreas Jaekel 	time_t op_time = rec->op_time;
21901c2c787SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
22001c2c787SAndreas Jaekel 
221d65b2fffSAndreas Jaekel 	if (verbose) {
222d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
223d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
224d65b2fffSAndreas Jaekel 		zpf("  mark.id: %llu", rec->mark_id);
225d65b2fffSAndreas Jaekel 		zpf("  payload.len: %llu", rec->payload_len);
226d65b2fffSAndreas Jaekel 		if (rec->payload_len)
227d65b2fffSAndreas Jaekel 			zev_print_mark_payload(rec);
228d65b2fffSAndreas Jaekel 		znl();
229d65b2fffSAndreas Jaekel 	} else {
23001c2c787SAndreas Jaekel 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
231d65b2fffSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
232d65b2fffSAndreas Jaekel 		       rec->mark_id, rec->payload_len);
233d65b2fffSAndreas Jaekel 	}
23401c2c787SAndreas Jaekel }
23501c2c787SAndreas Jaekel 
23601c2c787SAndreas Jaekel static void
23763aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
23863aba447SAndreas Jaekel {
23963aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
24063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
24163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
24263aba447SAndreas Jaekel 
243d65b2fffSAndreas Jaekel 	if (verbose) {
244d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
245d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
246d65b2fffSAndreas Jaekel 		zpf("  dataset: %s", ZEV_DATASET(rec));
247d65b2fffSAndreas Jaekel 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
248d65b2fffSAndreas Jaekel 		zpf("  remount: %s", rec->remount ? "true" : "false");
249d65b2fffSAndreas Jaekel 		zev_print_inode_info("root", &rec->root);
250d65b2fffSAndreas Jaekel 		znl();
251d65b2fffSAndreas Jaekel 	} else {
252d65b2fffSAndreas Jaekel 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
253d65b2fffSAndreas Jaekel 		       "mountpoint='%s'\n",
25463aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
25563aba447SAndreas Jaekel 		       rec->guid,
25663aba447SAndreas Jaekel 		       rec->remount ? "true" : "false",
25763aba447SAndreas Jaekel 		       ZEV_DATASET(rec),
25863aba447SAndreas Jaekel 		       ZEV_MOUNTPOINT(rec));
25963aba447SAndreas Jaekel 	}
260d65b2fffSAndreas Jaekel }
26163aba447SAndreas Jaekel 
26263aba447SAndreas Jaekel static void
26363aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
26463aba447SAndreas Jaekel {
26563aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
26663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
26763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
26863aba447SAndreas Jaekel 
269d65b2fffSAndreas Jaekel 	if (verbose) {
270d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
271d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
272d65b2fffSAndreas Jaekel 		znl();
273d65b2fffSAndreas Jaekel 	} else {
27463aba447SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
27563aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
27663aba447SAndreas Jaekel 		       rec->guid);
27763aba447SAndreas Jaekel 	}
278d65b2fffSAndreas Jaekel }
27963aba447SAndreas Jaekel 
28063aba447SAndreas Jaekel static void
28163aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
28263aba447SAndreas Jaekel {
28363aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
28463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
28563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
28663aba447SAndreas Jaekel 
287d65b2fffSAndreas Jaekel 	if (verbose) {
288d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
289d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
290e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
291d65b2fffSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
292d65b2fffSAndreas Jaekel 		zpf("  length: %llu", rec->length);
293d65b2fffSAndreas Jaekel 		znl();
294d65b2fffSAndreas Jaekel 	} else {
29563aba447SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
29663aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
29763aba447SAndreas Jaekel 		       rec->guid,
29863aba447SAndreas Jaekel 		       rec->offset,
29963aba447SAndreas Jaekel 		       rec->length);
30063aba447SAndreas Jaekel 	}
301d65b2fffSAndreas Jaekel }
30263aba447SAndreas Jaekel 
30363aba447SAndreas Jaekel static void
30463aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
30563aba447SAndreas Jaekel {
30663aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
30763aba447SAndreas Jaekel }
30863aba447SAndreas Jaekel 
30963aba447SAndreas Jaekel static void
31063aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
31163aba447SAndreas Jaekel {
31263aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
31363aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
31463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
31563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
31663aba447SAndreas Jaekel 
317d65b2fffSAndreas Jaekel 	if (verbose) {
318d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
319d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
320d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
321d65b2fffSAndreas Jaekel 		znl();
322d65b2fffSAndreas Jaekel 	} else {
32363aba447SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
32463aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
32563aba447SAndreas Jaekel 		       rec->guid,
32663aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
32763aba447SAndreas Jaekel 	}
328d65b2fffSAndreas Jaekel }
32963aba447SAndreas Jaekel 
33063aba447SAndreas Jaekel static void
33163aba447SAndreas Jaekel zev_print_znode_create(char *buf)
33263aba447SAndreas Jaekel {
33363aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
33463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
33563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
3361ca5a13bSAndreas Jaekel 	zev_sig_t *sig;
3371ca5a13bSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
33863aba447SAndreas Jaekel 
339d65b2fffSAndreas Jaekel 	if (verbose) {
340d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
341d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
342e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
343d65b2fffSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
3441ca5a13bSAndreas Jaekel 		sig = &rec->signature;
3451ca5a13bSAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
3461ca5a13bSAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
3471ca5a13bSAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
348d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
349e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
350d65b2fffSAndreas Jaekel 		znl();
351d65b2fffSAndreas Jaekel 	} else {
352c035b1e8SAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
353c035b1e8SAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
35463aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
35563aba447SAndreas Jaekel 		       rec->guid,
35663aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
35763aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
358c035b1e8SAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
35963aba447SAndreas Jaekel 		       ZEV_NAME(rec));
36063aba447SAndreas Jaekel 	}
361d65b2fffSAndreas Jaekel }
36263aba447SAndreas Jaekel 
36363aba447SAndreas Jaekel static void
36463aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
36563aba447SAndreas Jaekel {
36663aba447SAndreas Jaekel 	zev_print_znode_create(buf);
36763aba447SAndreas Jaekel }
36863aba447SAndreas Jaekel 
36963aba447SAndreas Jaekel static void
37063aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
37163aba447SAndreas Jaekel {
37263aba447SAndreas Jaekel 	zev_print_znode_create(buf);
37363aba447SAndreas Jaekel }
37463aba447SAndreas Jaekel 
37563aba447SAndreas Jaekel static void
37663aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
37763aba447SAndreas Jaekel {
37863aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
37963aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
38063aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
38163aba447SAndreas Jaekel 
382d65b2fffSAndreas Jaekel 	if (verbose) {
383d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
384d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
385e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
386d65b2fffSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
387d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
388e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
389d65b2fffSAndreas Jaekel 		znl();
390d65b2fffSAndreas Jaekel 	} else {
391d65b2fffSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
392d65b2fffSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
39363aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
39463aba447SAndreas Jaekel 		       rec->guid,
39563aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
3966db5d4ecSAndreas Jaekel 		       rec->file.mtime,
39763aba447SAndreas Jaekel 		       ZEV_NAME(rec));
39863aba447SAndreas Jaekel 	}
399d65b2fffSAndreas Jaekel }
40063aba447SAndreas Jaekel 
40163aba447SAndreas Jaekel static void
40263aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
40363aba447SAndreas Jaekel {
40463aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
40563aba447SAndreas Jaekel }
40663aba447SAndreas Jaekel 
40763aba447SAndreas Jaekel static void
40863aba447SAndreas Jaekel zev_print_znode_link(char *buf)
40963aba447SAndreas Jaekel {
41063aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
41163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
41263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
41363aba447SAndreas Jaekel 
414d65b2fffSAndreas Jaekel 	if (verbose) {
415d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
416d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
417e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
418d65b2fffSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
419d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
420e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
421d65b2fffSAndreas Jaekel 		znl();
422d65b2fffSAndreas Jaekel 	} else {
42303101f54SAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
42403101f54SAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
42563aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
42663aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
42763aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
42803101f54SAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
42963aba447SAndreas Jaekel 		       ZEV_NAME(rec));
430d65b2fffSAndreas Jaekel 	}
43163aba447SAndreas Jaekel }
43263aba447SAndreas Jaekel 
43363aba447SAndreas Jaekel static void
43463aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
43563aba447SAndreas Jaekel {
43663aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
43763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
43863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
4391ca5a13bSAndreas Jaekel 	zev_sig_t *sig;
4401ca5a13bSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
44163aba447SAndreas Jaekel 
442d65b2fffSAndreas Jaekel 	if (verbose) {
443d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
444d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
445e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
446d65b2fffSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
447d65b2fffSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
4481ca5a13bSAndreas Jaekel 		sig = &rec->signature;
4491ca5a13bSAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
4501ca5a13bSAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
4511ca5a13bSAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
452d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
453e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
454d65b2fffSAndreas Jaekel 		znl();
455d65b2fffSAndreas Jaekel 	} else {
456d65b2fffSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
457d65b2fffSAndreas Jaekel 		       "name='%s' link='%s'\n",
45863aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
45963aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
46063aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
46163aba447SAndreas Jaekel 		       ZEV_NAME(rec),
46263aba447SAndreas Jaekel 		       ZEV_LINK(rec));
46363aba447SAndreas Jaekel 	}
464d65b2fffSAndreas Jaekel }
46563aba447SAndreas Jaekel 
46663aba447SAndreas Jaekel static void
46763aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
46863aba447SAndreas Jaekel {
46963aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
47063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
47163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
47263aba447SAndreas Jaekel 
473d65b2fffSAndreas Jaekel 	if (verbose) {
474d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
475d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
476e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
477d65b2fffSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
478d65b2fffSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
479d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
480d65b2fffSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
481d65b2fffSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
482d65b2fffSAndreas Jaekel 		znl();
483d65b2fffSAndreas Jaekel 	} else {
484d65b2fffSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
485d65b2fffSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
486d65b2fffSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
487d65b2fffSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
48863aba447SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
48963aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
49063aba447SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
49163aba447SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
49263aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
493c035b1e8SAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
494c035b1e8SAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
495c035b1e8SAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
49663aba447SAndreas Jaekel 		       ZEV_SRCNAME(rec),
49763aba447SAndreas Jaekel 		       ZEV_DSTNAME(rec));
49863aba447SAndreas Jaekel 	}
499d65b2fffSAndreas Jaekel }
50063aba447SAndreas Jaekel 
50163aba447SAndreas Jaekel static void
50263aba447SAndreas Jaekel zev_print_znode_write(char *buf)
50363aba447SAndreas Jaekel {
50463aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
50563aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
50663aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
5075e286361SAndreas Jaekel 	zev_sig_t *sig;
5085e286361SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
5095e286361SAndreas Jaekel 	int i;
51063aba447SAndreas Jaekel 
5115e286361SAndreas Jaekel 	if (verbose) {
512d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
513d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
514e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
515d65b2fffSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
516d65b2fffSAndreas Jaekel 		zpf("  length: %llu", rec->length);
517d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
518d65b2fffSAndreas Jaekel 		znl();
5195e286361SAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
5205e286361SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
5215e286361SAndreas Jaekel 			sig += i;
5225e286361SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
5231ca5a13bSAndreas Jaekel 			zpf("  sig: level %d, offset %llu, value %s",
5245e286361SAndreas Jaekel 			    sig->level, sig->block_offset, sigval);
5255e286361SAndreas Jaekel 		}
526d65b2fffSAndreas Jaekel 	} else {
527d65b2fffSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
528d65b2fffSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
529d65b2fffSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
530d65b2fffSAndreas Jaekel 		       rec->offset, rec->length);
5315e286361SAndreas Jaekel 	}
53263aba447SAndreas Jaekel }
53363aba447SAndreas Jaekel 
53463aba447SAndreas Jaekel static void
53563aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
53663aba447SAndreas Jaekel {
53763aba447SAndreas Jaekel 	zev_print_znode_write(buf);
53863aba447SAndreas Jaekel }
53963aba447SAndreas Jaekel 
54063aba447SAndreas Jaekel static void
54163aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
54263aba447SAndreas Jaekel {
54363aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
54463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
54563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
54663aba447SAndreas Jaekel 
547d65b2fffSAndreas Jaekel 	if (verbose) {
548d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
549d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
550e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
551d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
552d65b2fffSAndreas Jaekel 		znl();
553d65b2fffSAndreas Jaekel 	} else {
554c035b1e8SAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
55563aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
556c035b1e8SAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
55763aba447SAndreas Jaekel 	}
558d65b2fffSAndreas Jaekel }
55963aba447SAndreas Jaekel 
56063aba447SAndreas Jaekel static void
56163aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
56263aba447SAndreas Jaekel {
56363aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
56463aba447SAndreas Jaekel }
56563aba447SAndreas Jaekel 
56663aba447SAndreas Jaekel static void
5679193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
5689193e9c2SAndreas Jaekel {
56963aba447SAndreas Jaekel 	int record_len;
57063aba447SAndreas Jaekel 	int op;
5719193e9c2SAndreas Jaekel 
57263aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
57363aba447SAndreas Jaekel 	if (record_len != len) {
57463aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
57563aba447SAndreas Jaekel 		        record_len, len);
5769193e9c2SAndreas Jaekel 		exit(1);
5779193e9c2SAndreas Jaekel 	}
57863aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
5799193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
58063aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
5819193e9c2SAndreas Jaekel 		exit(1);
5829193e9c2SAndreas Jaekel 	}
58363aba447SAndreas Jaekel 	switch (op) {
58463aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
58563aba447SAndreas Jaekel 		zev_print_error(buf);
5869193e9c2SAndreas Jaekel 		break;
58701c2c787SAndreas Jaekel 	case ZEV_OP_MARK:
58801c2c787SAndreas Jaekel 		zev_print_mark(buf);
58901c2c787SAndreas Jaekel 		break;
59063aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
59163aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
5929193e9c2SAndreas Jaekel 		break;
59363aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
59463aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
5959193e9c2SAndreas Jaekel 		break;
59663aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
59763aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
5989193e9c2SAndreas Jaekel 		break;
59963aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
60063aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
60163aba447SAndreas Jaekel 		break;
60263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
60363aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
60463aba447SAndreas Jaekel 		break;
60563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
60663aba447SAndreas Jaekel 		zev_print_znode_create(buf);
60763aba447SAndreas Jaekel 		break;
60863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
60963aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
61063aba447SAndreas Jaekel 		break;
61163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
61263aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
61363aba447SAndreas Jaekel 		break;
61463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
61563aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
61663aba447SAndreas Jaekel 		break;
61763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
61863aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
61963aba447SAndreas Jaekel 		break;
62063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
62163aba447SAndreas Jaekel 		zev_print_znode_link(buf);
62263aba447SAndreas Jaekel 		break;
62363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
62463aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
62563aba447SAndreas Jaekel 		break;
62663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
62763aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
62863aba447SAndreas Jaekel 		break;
62963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
63063aba447SAndreas Jaekel 		zev_print_znode_write(buf);
63163aba447SAndreas Jaekel 		break;
63263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
63363aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
63463aba447SAndreas Jaekel 		break;
63563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
63663aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
63763aba447SAndreas Jaekel 		break;
63863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
63963aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
6409193e9c2SAndreas Jaekel 		break;
6419193e9c2SAndreas Jaekel 	default:
64263aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
6439193e9c2SAndreas Jaekel 		exit(1);
6449193e9c2SAndreas Jaekel 	}
6459193e9c2SAndreas Jaekel }
6469193e9c2SAndreas Jaekel 
647e9a5e479SAndreas Jaekel static int
6484ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
6492bb8e5e2SAndreas Jaekel {
6502bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
6512bb8e5e2SAndreas Jaekel 	int ret;
6529193e9c2SAndreas Jaekel 	char buf[4096];
65368a46c64SAndreas Jaekel 	zev_event_t *ev;
65468a46c64SAndreas Jaekel 	int off = 0;
655e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
656e9a5e479SAndreas Jaekel 	int q_fd;
657e9a5e479SAndreas Jaekel 
6584ca7dd5eSAndreas Jaekel 	if (create_tmp_queue) {
659e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = 0;
660e9a5e479SAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
661e9a5e479SAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
662e9a5e479SAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
663e9a5e479SAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
664e9a5e479SAndreas Jaekel 
665e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
666e9a5e479SAndreas Jaekel 			perror("adding temporary queue failed");
667e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
668e9a5e479SAndreas Jaekel 		}
669e9a5e479SAndreas Jaekel 
6704ca7dd5eSAndreas Jaekel 		snprintf(buf, sizeof(buf),
6714ca7dd5eSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
672e9a5e479SAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
673e9a5e479SAndreas Jaekel 		if (q_fd < 0) {
674e9a5e479SAndreas Jaekel 			perror("opening queue device failed");
675e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
676e9a5e479SAndreas Jaekel 		}
6774ca7dd5eSAndreas Jaekel 	} else {
6784ca7dd5eSAndreas Jaekel 		q_fd = fd;
6794ca7dd5eSAndreas Jaekel 	}
680e9a5e479SAndreas Jaekel 
6812bb8e5e2SAndreas Jaekel 	while (1) {
682e9a5e479SAndreas Jaekel 		pfd[0].fd = q_fd;
6832bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
6842bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
6852bb8e5e2SAndreas Jaekel 		if (ret < 0) {
6862bb8e5e2SAndreas Jaekel 			perror("poll failed");
6874ca7dd5eSAndreas Jaekel 			close(q_fd);
688e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
6892bb8e5e2SAndreas Jaekel 		}
6902bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
6912bb8e5e2SAndreas Jaekel 			continue;
6922bb8e5e2SAndreas Jaekel 		/* data available */
693e9a5e479SAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
6942bb8e5e2SAndreas Jaekel 		if (ret < 0) {
6952bb8e5e2SAndreas Jaekel 			perror("read failed");
6964ca7dd5eSAndreas Jaekel 			close(q_fd);
697e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
6982bb8e5e2SAndreas Jaekel 		}
6992bb8e5e2SAndreas Jaekel 		if (ret == 0)
7002bb8e5e2SAndreas Jaekel 			continue;
70168a46c64SAndreas Jaekel 		while (ret > off) {
70268a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
70368a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
70468a46c64SAndreas Jaekel 			off += ev->header.record_len;
70568a46c64SAndreas Jaekel 		}
706108668daSAndreas Jaekel 		off = 0;
7072bb8e5e2SAndreas Jaekel 	}
7084ca7dd5eSAndreas Jaekel 	if (create_tmp_queue)
709e9a5e479SAndreas Jaekel 		close(q_fd);
710e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
7112bb8e5e2SAndreas Jaekel }
7122bb8e5e2SAndreas Jaekel 
7132bb8e5e2SAndreas Jaekel static void
7142bb8e5e2SAndreas Jaekel usage(char *progname)
7152bb8e5e2SAndreas Jaekel {
716e9a5e479SAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
717e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
718e9a5e479SAndreas Jaekel 	fprintf(stderr, " Status information:\n");
7192bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
7202bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
721e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
722e9a5e479SAndreas Jaekel 	        "information\n");
7230abdde4aSAndreas Jaekel 	fprintf(stderr, "   -T <interval> <cnt>  zevstat mode\n");
724e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
725e9a5e479SAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
726e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
727e9a5e479SAndreas Jaekel 	        "length\n");
728e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
729e9a5e479SAndreas Jaekel 	        "this pool\n");
7302bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
731e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
732e9a5e479SAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
733e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
7344ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
7354ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
736e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
737e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
738e9a5e479SAndreas Jaekel 	        "(default)\n");
739e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
740e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
7414ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
742e9a5e479SAndreas Jaekel 	        "length\n");
743e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
744e9a5e479SAndreas Jaekel 	        "throttle\n");
745e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
746e9a5e479SAndreas Jaekel 	fprintf(stderr, " Other options:\n");
747e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
748e9a5e479SAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
7494ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
7504ca7dd5eSAndreas Jaekel 		"queue name\n");
75101c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
752b9710123SAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
753b9710123SAndreas Jaekel 		"checksums\n");
754d65b2fffSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
7555e286361SAndreas Jaekel 	        "for some operations\n");
756d65b2fffSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
757d65b2fffSAndreas Jaekel 	        "one event per line\n");
7582bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
7592bb8e5e2SAndreas Jaekel }
7602bb8e5e2SAndreas Jaekel 
761*29fab2f9SAndreas Jaekel static void
762*29fab2f9SAndreas Jaekel zevstat_usage(char *progname)
763*29fab2f9SAndreas Jaekel {
764*29fab2f9SAndreas Jaekel 	fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname);
765*29fab2f9SAndreas Jaekel 	fprintf(stderr, "   -v   verbose, show counters for all event types\n");
766*29fab2f9SAndreas Jaekel 	exit (EXIT_FAILURE);
767*29fab2f9SAndreas Jaekel }
768*29fab2f9SAndreas Jaekel 
7692bb8e5e2SAndreas Jaekel static int
7704ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
7712bb8e5e2SAndreas Jaekel {
772e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
773e9a5e479SAndreas Jaekel 	int namelen;
7742bb8e5e2SAndreas Jaekel 
775e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
776e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
777e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
7782bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
7792bb8e5e2SAndreas Jaekel 	}
780e9a5e479SAndreas Jaekel 
781e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
782e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
7834ca7dd5eSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;
7844ca7dd5eSAndreas Jaekel 	if (blocking) {
7854ca7dd5eSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
7864ca7dd5eSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
7874ca7dd5eSAndreas Jaekel 	} else {
788e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
7894ca7dd5eSAndreas Jaekel 	}
790e9a5e479SAndreas Jaekel 
791e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
792e9a5e479SAndreas Jaekel 		perror("adding queue failed");
7932bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
7942bb8e5e2SAndreas Jaekel 	}
7952bb8e5e2SAndreas Jaekel 	return (0);
7962bb8e5e2SAndreas Jaekel }
7972bb8e5e2SAndreas Jaekel 
7982bb8e5e2SAndreas Jaekel static int
799e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg)
800205a9bc9SAndreas Jaekel {
801e9a5e479SAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
802e9a5e479SAndreas Jaekel 	int namelen;
803205a9bc9SAndreas Jaekel 
804e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
805e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
806e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
807205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
808205a9bc9SAndreas Jaekel 	}
809e9a5e479SAndreas Jaekel 
8104ca7dd5eSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
8114ca7dd5eSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
812e9a5e479SAndreas Jaekel 
813e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
814e9a5e479SAndreas Jaekel 		perror("removing queue failed");
815e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
816e9a5e479SAndreas Jaekel 	}
817e9a5e479SAndreas Jaekel 	return (0);
818e9a5e479SAndreas Jaekel }
819e9a5e479SAndreas Jaekel 
820e9a5e479SAndreas Jaekel static int
821e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
822e9a5e479SAndreas Jaekel {
823e9a5e479SAndreas Jaekel 	uint64_t maxqueuelen;
824e9a5e479SAndreas Jaekel 
825e9a5e479SAndreas Jaekel 	errno = 0;
826e9a5e479SAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
827e9a5e479SAndreas Jaekel 	if (errno) {
828e9a5e479SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
829e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
830e9a5e479SAndreas Jaekel 	}
831e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
832e9a5e479SAndreas Jaekel 		perror("setting max queue length failed");
833205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
834205a9bc9SAndreas Jaekel 	}
835205a9bc9SAndreas Jaekel 	return (0);
836205a9bc9SAndreas Jaekel }
837205a9bc9SAndreas Jaekel 
838205a9bc9SAndreas Jaekel static int
8392bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
8402bb8e5e2SAndreas Jaekel {
8412bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
8422bb8e5e2SAndreas Jaekel 	int len;
8432bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
8442bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
8452bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
8462bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
8472bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
8482bb8e5e2SAndreas Jaekel 	}
8492bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
8502bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
8512bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
8522bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
8532bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
8542bb8e5e2SAndreas Jaekel 	}
8552bb8e5e2SAndreas Jaekel 	return (0);
8562bb8e5e2SAndreas Jaekel }
8572bb8e5e2SAndreas Jaekel 
8582bb8e5e2SAndreas Jaekel int
8592bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
8602bb8e5e2SAndreas Jaekel {
8612bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
8622bb8e5e2SAndreas Jaekel }
8632bb8e5e2SAndreas Jaekel 
8642bb8e5e2SAndreas Jaekel int
8652bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
8662bb8e5e2SAndreas Jaekel {
8672bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
8682bb8e5e2SAndreas Jaekel }
8692bb8e5e2SAndreas Jaekel 
87001c2c787SAndreas Jaekel static int
871e9a5e479SAndreas Jaekel zev_debug_info(int fd)
872e9a5e479SAndreas Jaekel {
873e9a5e479SAndreas Jaekel 	zev_ioctl_debug_info_t di;
874e9a5e479SAndreas Jaekel 
875e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
876e9a5e479SAndreas Jaekel 		perror("getting zev debug info failed");
877e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
878e9a5e479SAndreas Jaekel 	}
879e9a5e479SAndreas Jaekel 
880e9a5e479SAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
8815e286361SAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
8825e286361SAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
8835e286361SAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
884e9a5e479SAndreas Jaekel 	return 0;
885e9a5e479SAndreas Jaekel }
886e9a5e479SAndreas Jaekel 
887e9a5e479SAndreas Jaekel static int
88801c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
88901c2c787SAndreas Jaekel {
89001c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
89101c2c787SAndreas Jaekel 	uint64_t guid;
89201c2c787SAndreas Jaekel 	int len;
89301c2c787SAndreas Jaekel 	char *p;
89401c2c787SAndreas Jaekel 
89501c2c787SAndreas Jaekel 	p = strchr(arg, ':');
89601c2c787SAndreas Jaekel 	if (!p) {
89701c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
89801c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
89901c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
90001c2c787SAndreas Jaekel 	}
90101c2c787SAndreas Jaekel 	*p = '\n';
90201c2c787SAndreas Jaekel 	p++;
90301c2c787SAndreas Jaekel 
90401c2c787SAndreas Jaekel 	errno = 0;
905e9a5e479SAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
90601c2c787SAndreas Jaekel 	if (errno) {
90701c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
90801c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
90901c2c787SAndreas Jaekel 	}
91001c2c787SAndreas Jaekel 
91101c2c787SAndreas Jaekel 	len = strlen(p);
91201c2c787SAndreas Jaekel 
91301c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
91401c2c787SAndreas Jaekel 	if (!mark) {
91501c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
91601c2c787SAndreas Jaekel 		        strerror(errno));
91701c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
91801c2c787SAndreas Jaekel 	}
91901c2c787SAndreas Jaekel 	mark->zev_guid = guid;
92001c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
92101c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
92201c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
92301c2c787SAndreas Jaekel 
92401c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
92501c2c787SAndreas Jaekel 		perror("queueing mark failed");
92601c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
92701c2c787SAndreas Jaekel 	}
92801c2c787SAndreas Jaekel 
92901c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
93001c2c787SAndreas Jaekel 	return (0);
93101c2c787SAndreas Jaekel }
93201c2c787SAndreas Jaekel 
933e9a5e479SAndreas Jaekel static int
934e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
935e9a5e479SAndreas Jaekel {
936e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
937e9a5e479SAndreas Jaekel 
9384ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9394ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
940e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
941e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
942e9a5e479SAndreas Jaekel 	}
9434ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
944e9a5e479SAndreas Jaekel 
945e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
946e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
947e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
948e9a5e479SAndreas Jaekel 	}
949e9a5e479SAndreas Jaekel 	if (block) {
950e9a5e479SAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
951e9a5e479SAndreas Jaekel 	} else {
952e9a5e479SAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
953e9a5e479SAndreas Jaekel 	}
954e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
955e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
956e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
957e9a5e479SAndreas Jaekel 	}
958e9a5e479SAndreas Jaekel 	return (0);
959e9a5e479SAndreas Jaekel }
960e9a5e479SAndreas Jaekel 
961e9a5e479SAndreas Jaekel static int
962e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
963e9a5e479SAndreas Jaekel {
964e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
965e9a5e479SAndreas Jaekel 
966e9a5e479SAndreas Jaekel 	if (!len) {
967e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
968e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
969e9a5e479SAndreas Jaekel 	}
970e9a5e479SAndreas Jaekel 
9714ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9724ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
973e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
974e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
975e9a5e479SAndreas Jaekel 	}
9764ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
977e9a5e479SAndreas Jaekel 
978e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
979e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
980e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
981e9a5e479SAndreas Jaekel 	}
982e9a5e479SAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
983e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
984e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
985e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
986e9a5e479SAndreas Jaekel 	}
987e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
988e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
989e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
990e9a5e479SAndreas Jaekel 	}
991e9a5e479SAndreas Jaekel 
992e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
993e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
994e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
995e9a5e479SAndreas Jaekel 	}
996e9a5e479SAndreas Jaekel 	return (0);
997e9a5e479SAndreas Jaekel }
998e9a5e479SAndreas Jaekel 
999e9a5e479SAndreas Jaekel static int
1000e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
1001e9a5e479SAndreas Jaekel {
1002e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1003e9a5e479SAndreas Jaekel 
1004e9a5e479SAndreas Jaekel 	if (!len) {
1005e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
1006e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1007e9a5e479SAndreas Jaekel 	}
1008e9a5e479SAndreas Jaekel 
10094ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10104ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1011e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1012e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1013e9a5e479SAndreas Jaekel 	}
10144ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1015e9a5e479SAndreas Jaekel 
1016e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1017e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
1018e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1019e9a5e479SAndreas Jaekel 	}
1020e9a5e479SAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
1021e9a5e479SAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
1022e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
1023e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1024e9a5e479SAndreas Jaekel 	}
10254ca7dd5eSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
1026e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
1027e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1028e9a5e479SAndreas Jaekel 	}
1029e9a5e479SAndreas Jaekel 
1030e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1031e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
1032e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1033e9a5e479SAndreas Jaekel 	}
1034e9a5e479SAndreas Jaekel 	return (0);
1035e9a5e479SAndreas Jaekel }
1036e9a5e479SAndreas Jaekel 
1037e9a5e479SAndreas Jaekel static int
1038e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg)
1039e9a5e479SAndreas Jaekel {
1040e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1041e9a5e479SAndreas Jaekel 
10424ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10434ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1044e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1045e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1046e9a5e479SAndreas Jaekel 	}
10474ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1048e9a5e479SAndreas Jaekel 
1049e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1050e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
1051e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1052e9a5e479SAndreas Jaekel 	}
1053e9a5e479SAndreas Jaekel 
1054e9a5e479SAndreas Jaekel 	printf("queue        : %s\n", arg);
1055e9a5e479SAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1056e9a5e479SAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1057e9a5e479SAndreas Jaekel 	printf("persistent   : %s\n",
1058e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1059e9a5e479SAndreas Jaekel 	printf("blocking     : %s\n",
1060e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1061e9a5e479SAndreas Jaekel 
1062e9a5e479SAndreas Jaekel 	return (0);
1063e9a5e479SAndreas Jaekel }
1064e9a5e479SAndreas Jaekel 
1065e9a5e479SAndreas Jaekel static int
1066e9a5e479SAndreas Jaekel zev_list_queues(int fd)
1067e9a5e479SAndreas Jaekel {
1068e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1069e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1070e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1071e9a5e479SAndreas Jaekel 	uint64_t	i;
1072e9a5e479SAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1073e9a5e479SAndreas Jaekel 
1074e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1075e9a5e479SAndreas Jaekel 		perror("getting queue list failed");
1076e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1077e9a5e479SAndreas Jaekel 	}
1078e9a5e479SAndreas Jaekel 
1079e9a5e479SAndreas Jaekel 	printf("Name                                     Size       "
1080e9a5e479SAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
1081e9a5e479SAndreas Jaekel 
1082e9a5e479SAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1083e9a5e479SAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1084e9a5e479SAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1085e9a5e479SAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1086e9a5e479SAndreas Jaekel 
10874ca7dd5eSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
10884ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
10894ca7dd5eSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
10904ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1091e9a5e479SAndreas Jaekel 
1092e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1093e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
1094e9a5e479SAndreas Jaekel 				continue;
1095e9a5e479SAndreas Jaekel 			perror("getting queue properties failed");
1096e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
1097e9a5e479SAndreas Jaekel 		}
1098e9a5e479SAndreas Jaekel 
10994ca7dd5eSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
11004ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11014ca7dd5eSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
11024ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1103e9a5e479SAndreas Jaekel 
1104e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1105e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
1106e9a5e479SAndreas Jaekel 				continue;
1107e9a5e479SAndreas Jaekel 			perror("getting statistics data failed");
1108e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
1109e9a5e479SAndreas Jaekel 		}
1110e9a5e479SAndreas Jaekel 
1111e9a5e479SAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
1112e9a5e479SAndreas Jaekel 		       " %-3s %-3s\n",
1113e9a5e479SAndreas Jaekel 			name,
1114e9a5e479SAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1115e9a5e479SAndreas Jaekel 			gqp.zev_max_queue_len,
1116e9a5e479SAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
1117e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1118e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1119e9a5e479SAndreas Jaekel 				 "yes" : "no");
1120e9a5e479SAndreas Jaekel 	}
1121e9a5e479SAndreas Jaekel 
1122e9a5e479SAndreas Jaekel 	return (0);
1123e9a5e479SAndreas Jaekel }
1124e9a5e479SAndreas Jaekel 
1125b9710123SAndreas Jaekel static int
1126b9710123SAndreas Jaekel zev_checksum(int dev_fd, char *filename)
1127b9710123SAndreas Jaekel {
1128b9710123SAndreas Jaekel 	int fd;
1129b9710123SAndreas Jaekel 	offset_t off;
1130b9710123SAndreas Jaekel 	offset_t data;
1131b9710123SAndreas Jaekel 	zev_sig_t *sig;
1132b9710123SAndreas Jaekel 	char *buf;
1133b9710123SAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
1134b9710123SAndreas Jaekel 	int i;
1135b9710123SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
1136b9710123SAndreas Jaekel 	int buf_size;
1137b9710123SAndreas Jaekel 
1138b9710123SAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
1139b9710123SAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
1140b9710123SAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
1141b9710123SAndreas Jaekel 	if (!buf) {
1142b9710123SAndreas Jaekel 		perror("can't allocate checksum buffer");
1143b9710123SAndreas Jaekel 		return (EXIT_FAILURE);
1144b9710123SAndreas Jaekel 	}
1145b9710123SAndreas Jaekel 
1146b9710123SAndreas Jaekel 	fd = open(filename, O_RDONLY);
1147b9710123SAndreas Jaekel 	if (fd < 0) {
1148b9710123SAndreas Jaekel 		perror("can't open file");
1149b9710123SAndreas Jaekel 		return (EXIT_FAILURE);
1150b9710123SAndreas Jaekel 	}
1151b9710123SAndreas Jaekel 
1152b9710123SAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
1153b9710123SAndreas Jaekel 	gs->zev_fd = fd;
1154b9710123SAndreas Jaekel 	gs->zev_bufsize = buf_size;
1155b9710123SAndreas Jaekel 
1156b9710123SAndreas Jaekel 	off = 0;
1157b9710123SAndreas Jaekel 	data = 0;
1158b9710123SAndreas Jaekel 	while (1) {
1159b9710123SAndreas Jaekel 		errno = 0;
1160b9710123SAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
1161b9710123SAndreas Jaekel 		if (data < 0) {
1162b9710123SAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
1163b9710123SAndreas Jaekel 				break;
1164b9710123SAndreas Jaekel 			perror("llseek failed");
1165b9710123SAndreas Jaekel 			goto err;
1166b9710123SAndreas Jaekel 		}
1167b9710123SAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
1168b9710123SAndreas Jaekel 		off = data + ZEV_L1_SIZE;
1169b9710123SAndreas Jaekel 
1170b9710123SAndreas Jaekel 		gs->zev_offset = data;
1171b9710123SAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
1172b9710123SAndreas Jaekel 
1173b9710123SAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
1174b9710123SAndreas Jaekel 			perror("ioctl to get signatures failed");
1175b9710123SAndreas Jaekel 			goto err;
1176b9710123SAndreas Jaekel 		}
1177b9710123SAndreas Jaekel 
1178b9710123SAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
1179b9710123SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
1180b9710123SAndreas Jaekel 			sig += i;
1181b9710123SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
1182b9710123SAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
1183b9710123SAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
1184b9710123SAndreas Jaekel 		}
1185b9710123SAndreas Jaekel 	}
1186b9710123SAndreas Jaekel 
1187b9710123SAndreas Jaekel 	free(buf);
1188b9710123SAndreas Jaekel 	close(fd);
1189b9710123SAndreas Jaekel 	return 0;
1190b9710123SAndreas Jaekel err:
1191b9710123SAndreas Jaekel 	free(buf);
1192b9710123SAndreas Jaekel 	close(fd);
1193b9710123SAndreas Jaekel 	return (EXIT_FAILURE);
1194b9710123SAndreas Jaekel }
1195b9710123SAndreas Jaekel 
11960abdde4aSAndreas Jaekel typedef struct zevstat {
11970abdde4aSAndreas Jaekel 	uint64_t	ns_start;
11980abdde4aSAndreas Jaekel 	uint64_t	events[ZEV_OP_MIN + ZEV_OP_MAX];
11990abdde4aSAndreas Jaekel 	uint64_t	guids;
12000abdde4aSAndreas Jaekel 	uint64_t	total_events;
12010abdde4aSAndreas Jaekel 	uint64_t	total_guids;
12020abdde4aSAndreas Jaekel 	avl_tree_t	guids_interval;
12030abdde4aSAndreas Jaekel 	avl_tree_t	guids_runtime;
12040abdde4aSAndreas Jaekel } zevstat_t;
12050abdde4aSAndreas Jaekel 
12060abdde4aSAndreas Jaekel typedef struct zev_guidtrack_t {
12070abdde4aSAndreas Jaekel 	uint64_t	guid;
12080abdde4aSAndreas Jaekel 	avl_node_t	avl_interval;
12090abdde4aSAndreas Jaekel 	avl_node_t	avl_runtime;
12100abdde4aSAndreas Jaekel } zev_guidtrack_t;
12110abdde4aSAndreas Jaekel 
12120abdde4aSAndreas Jaekel zevstat_t zevstat;
12130abdde4aSAndreas Jaekel 
12140abdde4aSAndreas Jaekel static void
12150abdde4aSAndreas Jaekel zev_eventstat(char *buf, int len)
12160abdde4aSAndreas Jaekel {
12170abdde4aSAndreas Jaekel 	zev_header_t *rec = (zev_header_t *)buf;
12180abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt;
12190abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt_int;
12200abdde4aSAndreas Jaekel 	zev_guidtrack_t to_find;
12210abdde4aSAndreas Jaekel 	avl_index_t where;
12220abdde4aSAndreas Jaekel 
12230abdde4aSAndreas Jaekel 	zevstat.total_events++;
12240abdde4aSAndreas Jaekel 	zevstat.events[rec->op]++;
12250abdde4aSAndreas Jaekel 
12260abdde4aSAndreas Jaekel 	to_find.guid = rec->guid;
12270abdde4aSAndreas Jaekel 	gt = avl_find(&zevstat.guids_runtime, &to_find, &where);
12280abdde4aSAndreas Jaekel 	if (!gt) {
12290abdde4aSAndreas Jaekel 		gt = malloc(sizeof(*gt));
12300abdde4aSAndreas Jaekel 		if (!gt) {
12310abdde4aSAndreas Jaekel 			perror("can't get guid tracking record");
12320abdde4aSAndreas Jaekel 			exit (EXIT_FAILURE);
12330abdde4aSAndreas Jaekel 		}
12340abdde4aSAndreas Jaekel 		gt->guid = rec->guid;
12350abdde4aSAndreas Jaekel 		avl_insert(&zevstat.guids_runtime, gt, where);
12360abdde4aSAndreas Jaekel 	}
12370abdde4aSAndreas Jaekel 	gt_int = avl_find(&zevstat.guids_interval, &to_find, &where);
12380abdde4aSAndreas Jaekel 	if (!gt_int)
12390abdde4aSAndreas Jaekel 		avl_insert(&zevstat.guids_interval, gt, where);
12400abdde4aSAndreas Jaekel }
12410abdde4aSAndreas Jaekel 
12420abdde4aSAndreas Jaekel static void
12430abdde4aSAndreas Jaekel zev_eventstat_interval(void)
12440abdde4aSAndreas Jaekel {
12450abdde4aSAndreas Jaekel 	uint64_t events;
12460abdde4aSAndreas Jaekel 	int i;
12470abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt;
12480abdde4aSAndreas Jaekel 
12490abdde4aSAndreas Jaekel 	events = 0;
12500abdde4aSAndreas Jaekel 	for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) {
12510abdde4aSAndreas Jaekel 		events += zevstat.events[i];
12520abdde4aSAndreas Jaekel 	}
12530abdde4aSAndreas Jaekel 
12540abdde4aSAndreas Jaekel 	if (verbose) {
12550abdde4aSAndreas Jaekel 		printf("%u  %6llu  %6llu %6llu %6llu  ",
12560abdde4aSAndreas Jaekel 		       time(NULL),
12570abdde4aSAndreas Jaekel 		       events,
12580abdde4aSAndreas Jaekel 		       zevstat.total_events,
12590abdde4aSAndreas Jaekel 		       avl_numnodes(&zevstat.guids_interval),
12600abdde4aSAndreas Jaekel 		       avl_numnodes(&zevstat.guids_runtime));
12610abdde4aSAndreas Jaekel 		for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++)
12620abdde4aSAndreas Jaekel 			printf("%6llu ", zevstat.events[i]);
12630abdde4aSAndreas Jaekel 		printf("\n");
12640abdde4aSAndreas Jaekel 	} else {
12650abdde4aSAndreas Jaekel 		printf("%u  %6llu  %6llu %6llu %6llu\n",
12660abdde4aSAndreas Jaekel 		       time(NULL),
12670abdde4aSAndreas Jaekel 		       events,
12680abdde4aSAndreas Jaekel 		       zevstat.total_events,
12690abdde4aSAndreas Jaekel 		       avl_numnodes(&zevstat.guids_interval),
12700abdde4aSAndreas Jaekel 		       avl_numnodes(&zevstat.guids_runtime));
12710abdde4aSAndreas Jaekel 	}
12720abdde4aSAndreas Jaekel 	memset(&zevstat.events, 0, sizeof(zevstat.events));
12730abdde4aSAndreas Jaekel 	zevstat.guids = 0;
12740abdde4aSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
12750abdde4aSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
12760abdde4aSAndreas Jaekel }
12770abdde4aSAndreas Jaekel 
12780abdde4aSAndreas Jaekel static int
12790abdde4aSAndreas Jaekel zev_evcompar(const void *a, const void *b)
12800abdde4aSAndreas Jaekel {
12810abdde4aSAndreas Jaekel 	const zev_guidtrack_t *ga = a;
12820abdde4aSAndreas Jaekel 	const zev_guidtrack_t *gb = b;
12830abdde4aSAndreas Jaekel 
12840abdde4aSAndreas Jaekel 	if (ga->guid > gb->guid)
12850abdde4aSAndreas Jaekel 		return 1;
12860abdde4aSAndreas Jaekel 	if (ga->guid < gb->guid)
12870abdde4aSAndreas Jaekel 		return -1;
12880abdde4aSAndreas Jaekel 	return 0;
12890abdde4aSAndreas Jaekel }
12900abdde4aSAndreas Jaekel 
12910abdde4aSAndreas Jaekel static int
12920abdde4aSAndreas Jaekel zev_zevstat(int fd, char *s_interval, char *s_count)
12930abdde4aSAndreas Jaekel {
12940abdde4aSAndreas Jaekel 	uint64_t interval = 1000;
12950abdde4aSAndreas Jaekel 	uint64_t ms;
12960abdde4aSAndreas Jaekel 	uint64_t t_until;
12970abdde4aSAndreas Jaekel 	uint64_t t_now;
12980abdde4aSAndreas Jaekel 	int cnt = -1;
12990abdde4aSAndreas Jaekel 	struct pollfd pfd[1];
13000abdde4aSAndreas Jaekel 	int ret;
13010abdde4aSAndreas Jaekel 	char buf[4096];
13020abdde4aSAndreas Jaekel 	zev_event_t *ev;
13030abdde4aSAndreas Jaekel 	int off = 0;
13040abdde4aSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
13050abdde4aSAndreas Jaekel 	int q_fd;
13060abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt;
13070abdde4aSAndreas Jaekel 
13080abdde4aSAndreas Jaekel 	memset(&zevstat, 0, sizeof(zevstat));
13090abdde4aSAndreas Jaekel 	avl_create(&zevstat.guids_runtime, zev_evcompar,
13100abdde4aSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
13110abdde4aSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_runtime));
13120abdde4aSAndreas Jaekel 	avl_create(&zevstat.guids_interval, zev_evcompar,
13130abdde4aSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
13140abdde4aSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_interval));
13150abdde4aSAndreas Jaekel 
1316ddaa5fcfSAndreas Jaekel 	if (s_interval) {
13170abdde4aSAndreas Jaekel 		interval = atol(s_interval);
13180abdde4aSAndreas Jaekel 		if (interval == 0) {
13190abdde4aSAndreas Jaekel 			fprintf(stderr, "invalid interval.\n");
13200abdde4aSAndreas Jaekel 			return (EXIT_FAILURE);
13210abdde4aSAndreas Jaekel 		}
13220abdde4aSAndreas Jaekel 		interval *= 1000;
1323ddaa5fcfSAndreas Jaekel 	}
13240abdde4aSAndreas Jaekel 	if (s_count) {
13250abdde4aSAndreas Jaekel 		cnt = atol(s_count);
13260abdde4aSAndreas Jaekel 		if (interval == 0) {
13270abdde4aSAndreas Jaekel 			fprintf(stderr, "invalid count.\n");
13280abdde4aSAndreas Jaekel 			return (EXIT_FAILURE);
13290abdde4aSAndreas Jaekel 		}
13300abdde4aSAndreas Jaekel 	}
13310abdde4aSAndreas Jaekel 
13320abdde4aSAndreas Jaekel 	aq.zev_max_queue_len = 1024 * 1024;
13330abdde4aSAndreas Jaekel 	aq.zev_flags = 0;
13340abdde4aSAndreas Jaekel 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
13350abdde4aSAndreas Jaekel 		 "zevstat.%ld.%ld", time(NULL), getpid());
13360abdde4aSAndreas Jaekel 	aq.zev_namelen = strlen(aq.zev_name);
13370abdde4aSAndreas Jaekel 
13380abdde4aSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
13390abdde4aSAndreas Jaekel 		perror("adding temporary queue failed");
13400abdde4aSAndreas Jaekel 		return (EXIT_FAILURE);
13410abdde4aSAndreas Jaekel 	}
13420abdde4aSAndreas Jaekel 
13430abdde4aSAndreas Jaekel 	snprintf(buf, sizeof(buf),
13440abdde4aSAndreas Jaekel 		 "/devices/pseudo/zev@0:%s", aq.zev_name);
13450abdde4aSAndreas Jaekel 	q_fd = open(buf, O_RDONLY);
13460abdde4aSAndreas Jaekel 	if (q_fd < 0) {
13470abdde4aSAndreas Jaekel 		perror("opening queue device failed");
13480abdde4aSAndreas Jaekel 		return (EXIT_FAILURE);
13490abdde4aSAndreas Jaekel 	}
13500abdde4aSAndreas Jaekel 
13510abdde4aSAndreas Jaekel 	pfd[0].fd = q_fd;
13520abdde4aSAndreas Jaekel 	pfd[0].events = POLLIN;
13530abdde4aSAndreas Jaekel 
13540abdde4aSAndreas Jaekel 	/* drain queue */
1355ddaa5fcfSAndreas Jaekel 	while ((ret = poll(pfd, 1, 0)) > 0) {
13560abdde4aSAndreas Jaekel 		if (read(q_fd, buf, sizeof(buf)) < 0) {
13570abdde4aSAndreas Jaekel 			perror("read failed");
13580abdde4aSAndreas Jaekel 			close(q_fd);
13590abdde4aSAndreas Jaekel 			return(EXIT_FAILURE);
13600abdde4aSAndreas Jaekel 		}
13610abdde4aSAndreas Jaekel 	}
13620abdde4aSAndreas Jaekel 	if (ret < 0) {
13630abdde4aSAndreas Jaekel 		perror("poll failed");
13640abdde4aSAndreas Jaekel 		close(q_fd);
13650abdde4aSAndreas Jaekel 		return(EXIT_FAILURE);
13660abdde4aSAndreas Jaekel 	}
13670abdde4aSAndreas Jaekel 
13680abdde4aSAndreas Jaekel 	printf("timestamp   events tevents  guids tguids");
13690abdde4aSAndreas Jaekel 	if (verbose) {
13700abdde4aSAndreas Jaekel 		printf("   error   mark  mount umount zvol_w zvol_t ");
13710abdde4aSAndreas Jaekel 		printf(" close create  mkdir mxattr remove  rmdir ");
13720abdde4aSAndreas Jaekel 		printf("  link symlnk rename  write  trunc setatt    acl");
13730abdde4aSAndreas Jaekel 	}
13740abdde4aSAndreas Jaekel 	printf("\n");
13750abdde4aSAndreas Jaekel 	while (cnt) {
13760abdde4aSAndreas Jaekel 		t_until = gethrtime() + (interval * 1000000);
13770abdde4aSAndreas Jaekel 		ms = interval;
13780abdde4aSAndreas Jaekel 		do {
13790abdde4aSAndreas Jaekel 			ret = poll(pfd, 1, ms);
13800abdde4aSAndreas Jaekel 			t_now = gethrtime();
13810abdde4aSAndreas Jaekel 			if (t_now < t_until) {
13820abdde4aSAndreas Jaekel 				ms = t_until - t_now;
13830abdde4aSAndreas Jaekel 				ms /= 1000000ull;
13840abdde4aSAndreas Jaekel 			}
13850abdde4aSAndreas Jaekel 			if (ret < 0) {
13860abdde4aSAndreas Jaekel 				perror("poll failed");
13870abdde4aSAndreas Jaekel 				close(q_fd);
13880abdde4aSAndreas Jaekel 				return(EXIT_FAILURE);
13890abdde4aSAndreas Jaekel 			}
13900abdde4aSAndreas Jaekel 			if (!(pfd[0].revents & POLLIN))
13910abdde4aSAndreas Jaekel 				continue;
13920abdde4aSAndreas Jaekel 			/* data available */
13930abdde4aSAndreas Jaekel 			ret = read(q_fd, buf, sizeof(buf));
13940abdde4aSAndreas Jaekel 			if (ret < 0) {
13950abdde4aSAndreas Jaekel 				perror("read failed");
13960abdde4aSAndreas Jaekel 				close(q_fd);
13970abdde4aSAndreas Jaekel 				return(EXIT_FAILURE);
13980abdde4aSAndreas Jaekel 			}
13990abdde4aSAndreas Jaekel 			if (ret == 0)
14000abdde4aSAndreas Jaekel 				continue;
14010abdde4aSAndreas Jaekel 			while (ret > off) {
14020abdde4aSAndreas Jaekel 				ev = (zev_event_t *)(buf + off);
14030abdde4aSAndreas Jaekel 				zev_eventstat(buf + off, ev->header.record_len);
14040abdde4aSAndreas Jaekel 				off += ev->header.record_len;
14050abdde4aSAndreas Jaekel 			}
14060abdde4aSAndreas Jaekel 			off = 0;
14070abdde4aSAndreas Jaekel 		} while ((t_now) < t_until && (ms > 0));
14080abdde4aSAndreas Jaekel 		zev_eventstat_interval();
14090abdde4aSAndreas Jaekel 		if (cnt > 0)
14100abdde4aSAndreas Jaekel 			cnt--;
14110abdde4aSAndreas Jaekel 	}
14120abdde4aSAndreas Jaekel 	close(q_fd);
14130abdde4aSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
14140abdde4aSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
14150abdde4aSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_runtime)) {
14160abdde4aSAndreas Jaekel 		avl_remove(&zevstat.guids_runtime, gt);
14170abdde4aSAndreas Jaekel 		free(gt);
14180abdde4aSAndreas Jaekel 	}
14190abdde4aSAndreas Jaekel 	return EXIT_SUCCESS;
14200abdde4aSAndreas Jaekel }
14210abdde4aSAndreas Jaekel 
14222bb8e5e2SAndreas Jaekel int
14232bb8e5e2SAndreas Jaekel main(int argc, char **argv)
14242bb8e5e2SAndreas Jaekel {
14252bb8e5e2SAndreas Jaekel 	int fd;
14262bb8e5e2SAndreas Jaekel 	int c;
14272bb8e5e2SAndreas Jaekel 	extern char *optarg;
14284ca7dd5eSAndreas Jaekel 	int create_tmp_queue = 1;
14294ca7dd5eSAndreas Jaekel 	char buf[MAXPATHLEN];
14306a3d43bfSAndreas Jaekel 	int mode = 0;
14316a3d43bfSAndreas Jaekel 	char *arg = NULL;
14326a3d43bfSAndreas Jaekel 	char *arg2 = NULL;
14330abdde4aSAndreas Jaekel 	char *p;
14340abdde4aSAndreas Jaekel 
1435*29fab2f9SAndreas Jaekel 	/* open device */
1436*29fab2f9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
1437*29fab2f9SAndreas Jaekel 	if (fd < 0) {
1438*29fab2f9SAndreas Jaekel 		perror("opening zev device failed");
1439*29fab2f9SAndreas Jaekel 		return EXIT_FAILURE;
1440*29fab2f9SAndreas Jaekel 	}
1441*29fab2f9SAndreas Jaekel 
14420abdde4aSAndreas Jaekel 	p = strrchr(argv[0], '/');
14430abdde4aSAndreas Jaekel 	if (!p) {
14440abdde4aSAndreas Jaekel 		p = argv[0];
14450abdde4aSAndreas Jaekel 	} else {
14460abdde4aSAndreas Jaekel 		p++;
14470abdde4aSAndreas Jaekel 	}
14480abdde4aSAndreas Jaekel 	if (!strcmp(p, "zevstat")) {
14490abdde4aSAndreas Jaekel 		mode = MD_ZEVSTAT;
1450*29fab2f9SAndreas Jaekel 		if (argc < 2)
1451*29fab2f9SAndreas Jaekel 			zevstat_usage(argv[0]);
1452*29fab2f9SAndreas Jaekel 		if (!strcmp(argv[1], "-v")) {
1453*29fab2f9SAndreas Jaekel 			if (argc < 3)
1454*29fab2f9SAndreas Jaekel 				zevstat_usage(argv[0]);
1455*29fab2f9SAndreas Jaekel 			verbose++;
1456*29fab2f9SAndreas Jaekel 			arg = argv[2];
1457*29fab2f9SAndreas Jaekel 			arg2 = argv[3];
1458*29fab2f9SAndreas Jaekel 		} else {
1459*29fab2f9SAndreas Jaekel 			arg = argv[1];
1460*29fab2f9SAndreas Jaekel 			arg2 = argv[2];
1461*29fab2f9SAndreas Jaekel 		}
1462*29fab2f9SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2);
14630abdde4aSAndreas Jaekel 	}
14642bb8e5e2SAndreas Jaekel 
14654ca7dd5eSAndreas Jaekel 	while ((c = getopt(argc, argv,
14660abdde4aSAndreas Jaekel 	                   "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:T:h?")) != -1){
14672bb8e5e2SAndreas Jaekel 		switch(c) {
1468d65b2fffSAndreas Jaekel 		case 'g':
1469d65b2fffSAndreas Jaekel 			grep_friendly++;
1470d65b2fffSAndreas Jaekel 			verbose++;
1471d65b2fffSAndreas Jaekel 			break;
14725e286361SAndreas Jaekel 		case 'v':
14735e286361SAndreas Jaekel 			verbose++;
14745e286361SAndreas Jaekel 			break;
14752bb8e5e2SAndreas Jaekel 		case 's':
14766a3d43bfSAndreas Jaekel 			mode = MD_STATISTICS;
14776a3d43bfSAndreas Jaekel 			break;
14782bb8e5e2SAndreas Jaekel 		case 'p':
14796a3d43bfSAndreas Jaekel 			mode = MD_POLL_EVENTS;
14806a3d43bfSAndreas Jaekel 			break;
1481b9710123SAndreas Jaekel 		case 'c':
14826a3d43bfSAndreas Jaekel 			mode = MD_CHECKSUMS;
14836a3d43bfSAndreas Jaekel 			arg = optarg;
14846a3d43bfSAndreas Jaekel 			break;
1485e9a5e479SAndreas Jaekel 		case 'D':
14866a3d43bfSAndreas Jaekel 			mode = MD_DEBUG_INFO;
14876a3d43bfSAndreas Jaekel 			break;
14882bb8e5e2SAndreas Jaekel 		case 'd':
1489e9a5e479SAndreas Jaekel 			close(fd);
14902bb8e5e2SAndreas Jaekel 			zev_device = optarg;
1491e9a5e479SAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1492e9a5e479SAndreas Jaekel 			if (fd < 0) {
1493e9a5e479SAndreas Jaekel 				perror("opening zev device failed");
1494e9a5e479SAndreas Jaekel 				return EXIT_FAILURE;
1495e9a5e479SAndreas Jaekel 			}
14964ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
14974ca7dd5eSAndreas Jaekel 			break;
14984ca7dd5eSAndreas Jaekel 		case 'q':
14994ca7dd5eSAndreas Jaekel 			snprintf(buf, sizeof(buf),
15004ca7dd5eSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
15014ca7dd5eSAndreas Jaekel 			close(fd);
15024ca7dd5eSAndreas Jaekel 			zev_device = buf;
15034ca7dd5eSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
15044ca7dd5eSAndreas Jaekel 			if (fd < 0) {
15054ca7dd5eSAndreas Jaekel 				perror("opening zev device failed");
15064ca7dd5eSAndreas Jaekel 				return EXIT_FAILURE;
15074ca7dd5eSAndreas Jaekel 			}
15084ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
15092bb8e5e2SAndreas Jaekel 			break;
1510e9a5e479SAndreas Jaekel 		case 'l':
15116a3d43bfSAndreas Jaekel 			mode = MD_LIST_QUEUES;
15126a3d43bfSAndreas Jaekel 			break;
1513e9a5e479SAndreas Jaekel 		case 'Q':
15146a3d43bfSAndreas Jaekel 			mode = MD_SET_GLOBAL_MAX_QUEUE_LEN;
15156a3d43bfSAndreas Jaekel 			arg = optarg;
15166a3d43bfSAndreas Jaekel 			break;
15174ca7dd5eSAndreas Jaekel 		case 'L':
15186a3d43bfSAndreas Jaekel 			mode = MD_SET_MAX_QUEUE_LEN;
15196a3d43bfSAndreas Jaekel 			arg = optarg;
15206a3d43bfSAndreas Jaekel 			arg2 = argv[optind];
15216a3d43bfSAndreas Jaekel 			break;
15220abdde4aSAndreas Jaekel 		case 'T':
15230abdde4aSAndreas Jaekel 			mode = MD_ZEVSTAT;
15240abdde4aSAndreas Jaekel 			arg = optarg;
15250abdde4aSAndreas Jaekel 			arg2 = argv[optind];
15260abdde4aSAndreas Jaekel 			break;
1527205a9bc9SAndreas Jaekel 		case 't':
15286a3d43bfSAndreas Jaekel 			mode = MD_SET_POLL_WAKEUP_QUEUE_LEN;
15296a3d43bfSAndreas Jaekel 			arg = optarg;
15306a3d43bfSAndreas Jaekel 			arg2 = argv[optind];
15316a3d43bfSAndreas Jaekel 			break;
15322bb8e5e2SAndreas Jaekel 		case 'm':
15336a3d43bfSAndreas Jaekel 			mode = MD_MUTE_POOL;
15346a3d43bfSAndreas Jaekel 			arg = optarg;
15356a3d43bfSAndreas Jaekel 			break;
15362bb8e5e2SAndreas Jaekel 		case 'M':
15376a3d43bfSAndreas Jaekel 			mode = MD_UNMUTE_POOL;
15386a3d43bfSAndreas Jaekel 			arg = optarg;
15396a3d43bfSAndreas Jaekel 			break;
154001c2c787SAndreas Jaekel 		case 'k':
15416a3d43bfSAndreas Jaekel 			mode = MD_MARK;
15426a3d43bfSAndreas Jaekel 			arg = optarg;
15436a3d43bfSAndreas Jaekel 			break;
1544e9a5e479SAndreas Jaekel 		case 'a':
15456a3d43bfSAndreas Jaekel 			mode = MD_ADD_QUEUE;
15466a3d43bfSAndreas Jaekel 			arg = optarg;
15476a3d43bfSAndreas Jaekel 			break;
15484ca7dd5eSAndreas Jaekel 		case 'A':
15496a3d43bfSAndreas Jaekel 			mode = MD_ADD_BLOCKING_QUEUE;
15506a3d43bfSAndreas Jaekel 			arg = optarg;
15516a3d43bfSAndreas Jaekel 			break;
1552e9a5e479SAndreas Jaekel 		case 'r':
15536a3d43bfSAndreas Jaekel 			mode = MD_REMOVE_QUEUE;
15546a3d43bfSAndreas Jaekel 			arg = optarg;
15556a3d43bfSAndreas Jaekel 			break;
1556e9a5e479SAndreas Jaekel 		case 'b':
15576a3d43bfSAndreas Jaekel 			mode = MD_QUEUE_BLOCKING;
15586a3d43bfSAndreas Jaekel 			arg = optarg;
15596a3d43bfSAndreas Jaekel 			break;
1560e9a5e479SAndreas Jaekel 		case 'B':
15616a3d43bfSAndreas Jaekel 			mode = MD_QUEUE_NONBLOCKING;
15626a3d43bfSAndreas Jaekel 			arg = optarg;
15636a3d43bfSAndreas Jaekel 			break;
1564e9a5e479SAndreas Jaekel 		case 'P':
15656a3d43bfSAndreas Jaekel 			mode = MD_QUEUE_PROPERTIES;
15666a3d43bfSAndreas Jaekel 			arg = optarg;
15676a3d43bfSAndreas Jaekel 			break;
15682bb8e5e2SAndreas Jaekel 		case 'h':
15692bb8e5e2SAndreas Jaekel 		case '?':
15702bb8e5e2SAndreas Jaekel 		default:
15712bb8e5e2SAndreas Jaekel 			usage(argv[0]);
15722bb8e5e2SAndreas Jaekel 		}
15732bb8e5e2SAndreas Jaekel 	}
15746a3d43bfSAndreas Jaekel 
15756a3d43bfSAndreas Jaekel 	switch (mode) {
15766a3d43bfSAndreas Jaekel 	case MD_STATISTICS:
15776a3d43bfSAndreas Jaekel 		return zev_statistics(fd);
15786a3d43bfSAndreas Jaekel 	case MD_POLL_EVENTS:
15796a3d43bfSAndreas Jaekel 		return zev_poll_events(fd, create_tmp_queue);
15806a3d43bfSAndreas Jaekel 	case MD_CHECKSUMS:
15816a3d43bfSAndreas Jaekel 		return zev_checksum(fd, arg);
15826a3d43bfSAndreas Jaekel 	case MD_DEBUG_INFO:
15836a3d43bfSAndreas Jaekel 		return zev_debug_info(fd);
15846a3d43bfSAndreas Jaekel 	case MD_LIST_QUEUES:
15856a3d43bfSAndreas Jaekel 		return zev_list_queues(fd);
15866a3d43bfSAndreas Jaekel 	case MD_SET_GLOBAL_MAX_QUEUE_LEN:
15876a3d43bfSAndreas Jaekel 		return zev_set_global_max_queue_len(fd, arg);
15886a3d43bfSAndreas Jaekel 	case MD_SET_MAX_QUEUE_LEN:
15896a3d43bfSAndreas Jaekel 		return zev_set_max_queue_len(fd, arg, arg2);
15906a3d43bfSAndreas Jaekel 	case MD_SET_POLL_WAKEUP_QUEUE_LEN:
15916a3d43bfSAndreas Jaekel 		return zev_set_poll_wakeup_queue_len(fd, arg, arg2);
15920abdde4aSAndreas Jaekel 	case MD_ZEVSTAT:
15930abdde4aSAndreas Jaekel 		return zev_zevstat(fd, arg, arg2);
15946a3d43bfSAndreas Jaekel 	case MD_MUTE_POOL:
15956a3d43bfSAndreas Jaekel 		return zev_mute_pool(fd, arg);
15966a3d43bfSAndreas Jaekel 	case MD_UNMUTE_POOL:
15976a3d43bfSAndreas Jaekel 		return zev_unmute_pool(fd, arg);
15986a3d43bfSAndreas Jaekel 	case MD_MARK:
15996a3d43bfSAndreas Jaekel 		return zev_mark(fd, arg);
16006a3d43bfSAndreas Jaekel 	case MD_ADD_QUEUE:
16016a3d43bfSAndreas Jaekel 		return zev_add_queue(fd, arg, 0);
16026a3d43bfSAndreas Jaekel 	case MD_ADD_BLOCKING_QUEUE:
16036a3d43bfSAndreas Jaekel 		return zev_add_queue(fd, arg, 1);
16046a3d43bfSAndreas Jaekel 	case MD_REMOVE_QUEUE:
16056a3d43bfSAndreas Jaekel 		return zev_remove_queue(fd, arg);
16066a3d43bfSAndreas Jaekel 	case MD_QUEUE_BLOCKING:
16076a3d43bfSAndreas Jaekel 		return zev_queue_blocking(fd, arg, 0);
16086a3d43bfSAndreas Jaekel 	case MD_QUEUE_NONBLOCKING:
16096a3d43bfSAndreas Jaekel 		return zev_queue_blocking(fd, arg, 1);
16106a3d43bfSAndreas Jaekel 	case MD_QUEUE_PROPERTIES:
16116a3d43bfSAndreas Jaekel 		return zev_queue_properties(fd, arg);
16126a3d43bfSAndreas Jaekel 	default:
16132bb8e5e2SAndreas Jaekel 		close(fd);
16146a3d43bfSAndreas Jaekel 		usage(argv[0]);
1615e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
16166a3d43bfSAndreas Jaekel 	};
16172bb8e5e2SAndreas Jaekel }
16182bb8e5e2SAndreas Jaekel 
1619