xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision c99a1a257f8a5ec43b8896d8e5e51b50c7f09883)
1a18c35b9SAndreas Jaekel #include <stdio.h>
2a18c35b9SAndreas Jaekel #include <unistd.h>
3a18c35b9SAndreas Jaekel #include <stdlib.h>
4a18c35b9SAndreas Jaekel #include <fcntl.h>
5a18c35b9SAndreas Jaekel #include <stropts.h>
6a18c35b9SAndreas Jaekel #include <poll.h>
7a18c35b9SAndreas Jaekel #include <string.h>
8a18c35b9SAndreas Jaekel #include <sys/fs/zev.h>
9a18c35b9SAndreas Jaekel #include <errno.h>
1042110aacSAndreas Jaekel #include <sys/sysmacros.h>
1116ff6b2fSAndreas Jaekel #include <stdarg.h>
12b690436dSAndreas Jaekel #include <sys/avl.h>
13f432e238SAndreas Jaekel #include <sys/stat.h>
14a18c35b9SAndreas Jaekel 
15add9520fSAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
16a18c35b9SAndreas Jaekel 
17b690436dSAndreas Jaekel #if !defined(offsetof)
18b690436dSAndreas Jaekel #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
19b690436dSAndreas Jaekel #endif
20b690436dSAndreas Jaekel 
21a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
22a18c35b9SAndreas Jaekel 
23aafc540fSAndreas Jaekel static char *zev_op_name[] = {
2416ff6b2fSAndreas Jaekel 	"ERROR",
2516ff6b2fSAndreas Jaekel 	"MARK",
2616ff6b2fSAndreas Jaekel 	"ZFS_MOUNT",
2716ff6b2fSAndreas Jaekel 	"ZFS_UMOUNT",
2816ff6b2fSAndreas Jaekel 	"ZVOL_WRITE",
2916ff6b2fSAndreas Jaekel 	"ZVOL_TRUNCATE",
3016ff6b2fSAndreas Jaekel 	"ZNODE_CLOSE_AFTER_UPDATE",
3116ff6b2fSAndreas Jaekel 	"ZNODE_CREATE",
3216ff6b2fSAndreas Jaekel 	"ZNODE_MKDIR",
3316ff6b2fSAndreas Jaekel 	"ZNODE_MAKE_XATTR_DIR",
3416ff6b2fSAndreas Jaekel 	"ZNODE_REMOVE",
3516ff6b2fSAndreas Jaekel 	"ZNODE_RMDIR",
3616ff6b2fSAndreas Jaekel 	"ZNODE_LINK",
3716ff6b2fSAndreas Jaekel 	"ZNODE_SYMLINK",
3816ff6b2fSAndreas Jaekel 	"ZNODE_RENAME",
3916ff6b2fSAndreas Jaekel 	"ZNODE_WRITE",
4016ff6b2fSAndreas Jaekel 	"ZNODE_TRUNCATE",
4116ff6b2fSAndreas Jaekel 	"ZNODE_SETATTR",
4216ff6b2fSAndreas Jaekel 	"ZNODE_ACL",
43aafc540fSAndreas Jaekel 	NULL
44aafc540fSAndreas Jaekel };
45aafc540fSAndreas Jaekel 
46a5090b97SAndreas Jaekel #define MD_STATISTICS			1
47a5090b97SAndreas Jaekel #define MD_POLL_EVENTS			2
48a5090b97SAndreas Jaekel #define MD_CHECKSUMS			3
49a5090b97SAndreas Jaekel #define MD_DEBUG_INFO			4
50a5090b97SAndreas Jaekel #define MD_LIST_QUEUES			5
51a5090b97SAndreas Jaekel #define MD_SET_GLOBAL_MAX_QUEUE_LEN	6
52a5090b97SAndreas Jaekel #define MD_SET_MAX_QUEUE_LEN		7
53a5090b97SAndreas Jaekel #define MD_SET_POLL_WAKEUP_QUEUE_LEN	8
54a5090b97SAndreas Jaekel #define MD_MUTE_POOL			9
55a5090b97SAndreas Jaekel #define MD_UNMUTE_POOL			10
56a5090b97SAndreas Jaekel #define MD_MARK				11
57a5090b97SAndreas Jaekel #define MD_ADD_QUEUE			12
58a5090b97SAndreas Jaekel #define MD_ADD_BLOCKING_QUEUE		13
59a5090b97SAndreas Jaekel #define MD_REMOVE_QUEUE			14
60a5090b97SAndreas Jaekel #define MD_QUEUE_BLOCKING		15
61a5090b97SAndreas Jaekel #define MD_QUEUE_NONBLOCKING		16
62a5090b97SAndreas Jaekel #define MD_QUEUE_PROPERTIES		17
63b690436dSAndreas Jaekel #define MD_ZEVSTAT			18
64f432e238SAndreas Jaekel #define MD_ZEV_REPORT			19
65a5090b97SAndreas Jaekel 
66205ed6bfSAndreas Jaekel static int verbose = 0;
6716ff6b2fSAndreas Jaekel static int grep_friendly = 0;
6816ff6b2fSAndreas Jaekel 
6916ff6b2fSAndreas Jaekel static void
7016ff6b2fSAndreas Jaekel zpf(char *fmt, ...)
7116ff6b2fSAndreas Jaekel {
7216ff6b2fSAndreas Jaekel 	va_list	ap;
7316ff6b2fSAndreas Jaekel 
7416ff6b2fSAndreas Jaekel 	va_start(ap, fmt);
7516ff6b2fSAndreas Jaekel 	vprintf(fmt, ap);
7616ff6b2fSAndreas Jaekel 	va_end(ap);
7716ff6b2fSAndreas Jaekel 	if (grep_friendly) {
7816ff6b2fSAndreas Jaekel 		printf(" ");
7916ff6b2fSAndreas Jaekel 	} else {
8016ff6b2fSAndreas Jaekel 		printf("\n");
8116ff6b2fSAndreas Jaekel 	}
8216ff6b2fSAndreas Jaekel }
8316ff6b2fSAndreas Jaekel 
8416ff6b2fSAndreas Jaekel static void
8516ff6b2fSAndreas Jaekel znl(void)
8616ff6b2fSAndreas Jaekel {
8716ff6b2fSAndreas Jaekel 	if (grep_friendly)
8816ff6b2fSAndreas Jaekel 		printf("\n");
8916ff6b2fSAndreas Jaekel }
90205ed6bfSAndreas Jaekel 
912eabeab5SAndreas Jaekel static void
922eabeab5SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
932eabeab5SAndreas Jaekel {
942eabeab5SAndreas Jaekel 	int     i;
952eabeab5SAndreas Jaekel 
962eabeab5SAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
972eabeab5SAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
982eabeab5SAndreas Jaekel 	}
992eabeab5SAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
1002eabeab5SAndreas Jaekel }
1012eabeab5SAndreas Jaekel 
102add9520fSAndreas Jaekel static int
103a18c35b9SAndreas Jaekel zev_statistics(int fd)
104a18c35b9SAndreas Jaekel {
105a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
106add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
107a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
108add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
109a18c35b9SAndreas Jaekel 	}
110a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
111a18c35b9SAndreas Jaekel 
112a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
113a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
114a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
115a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
116a18c35b9SAndreas Jaekel 
117add9520fSAndreas Jaekel 	printf("    discarded events        : %lu\n",
118add9520fSAndreas Jaekel 	    zs.zev_cnt_discarded_events);
119add9520fSAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
120add9520fSAndreas Jaekel 
121a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
122a18c35b9SAndreas Jaekel 
123a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
124a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
125a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
126a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
127a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
128a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
129a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
130a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
131a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
132a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
133a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
134a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
135a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
136a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
137a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
138a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
139a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
140add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
141a18c35b9SAndreas Jaekel }
142a18c35b9SAndreas Jaekel 
143a18c35b9SAndreas Jaekel static void
14416ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info)
14516ff6b2fSAndreas Jaekel {
14616ff6b2fSAndreas Jaekel 	zpf("  %s.inode: %llu", name, info->ino);
14716ff6b2fSAndreas Jaekel 	zpf("  %s.gen: %llu", name, info->gen);
14816ff6b2fSAndreas Jaekel 	zpf("  %s.mtime: %llu", name, info->mtime);
14916ff6b2fSAndreas Jaekel 	zpf("  %s.ctime: %llu", name, info->ctime);
15016ff6b2fSAndreas Jaekel 	zpf("  %s.size: %llu", name, info->size);
15116ff6b2fSAndreas Jaekel 	zpf("  %s.mode: %llo", name, info->mode);
15216ff6b2fSAndreas Jaekel 	zpf("  %s.links: %llu", name, info->links);
15316ff6b2fSAndreas Jaekel 	zpf("  %s.type: %lu", name, info->type);
15416ff6b2fSAndreas Jaekel 	zpf("  %s.flags: %lu", name, info->flags);
15516ff6b2fSAndreas Jaekel }
15616ff6b2fSAndreas Jaekel 
15716ff6b2fSAndreas Jaekel static void
15816ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec)
15916ff6b2fSAndreas Jaekel {
16016ff6b2fSAndreas Jaekel 	int i;
16116ff6b2fSAndreas Jaekel 	int j;
16216ff6b2fSAndreas Jaekel 	uint8_t *p;
16316ff6b2fSAndreas Jaekel 	char c;
16416ff6b2fSAndreas Jaekel 
16516ff6b2fSAndreas Jaekel 	zpf("  payload:");
16616ff6b2fSAndreas Jaekel 	p = (uint8_t *)ZEV_PAYLOAD(rec);
16716ff6b2fSAndreas Jaekel 	for (i=0; i<rec->payload_len; i+=16) {
16816ff6b2fSAndreas Jaekel 		printf("  ");
16916ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
17016ff6b2fSAndreas Jaekel 			printf("%02x ", p[j]);
17116ff6b2fSAndreas Jaekel 			if (j == i + 7)
17216ff6b2fSAndreas Jaekel 				printf(" ");
17316ff6b2fSAndreas Jaekel 		}
17416ff6b2fSAndreas Jaekel 		if (grep_friendly)
17516ff6b2fSAndreas Jaekel 			continue;
17616ff6b2fSAndreas Jaekel 		for (; j<i+16; j++) {
17716ff6b2fSAndreas Jaekel 			printf("   ");
17816ff6b2fSAndreas Jaekel 			if (j == i + 7)
17916ff6b2fSAndreas Jaekel 				printf(" ");
18016ff6b2fSAndreas Jaekel 		}
18116ff6b2fSAndreas Jaekel 		printf("    ");
18216ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
18316ff6b2fSAndreas Jaekel 			c = '.';
18416ff6b2fSAndreas Jaekel 			if (p[j] >= ' ' && p[j] <= '~')
18516ff6b2fSAndreas Jaekel 				c = p[j];
18616ff6b2fSAndreas Jaekel 			printf("%c", c);
18716ff6b2fSAndreas Jaekel 			if (j == i + 7)
18816ff6b2fSAndreas Jaekel 				printf(" ");
18916ff6b2fSAndreas Jaekel 		}
19016ff6b2fSAndreas Jaekel 		printf("\n");
19116ff6b2fSAndreas Jaekel 	}
19216ff6b2fSAndreas Jaekel }
19316ff6b2fSAndreas Jaekel 
19416ff6b2fSAndreas Jaekel static void
195f2dd45e5SAndreas Jaekel zev_print_error(char *buf)
196f2dd45e5SAndreas Jaekel {
197f2dd45e5SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
198f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
199f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
200f2dd45e5SAndreas Jaekel 
20116ff6b2fSAndreas Jaekel 	if (verbose) {
20216ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
20316ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
20416ff6b2fSAndreas Jaekel 		zpf("  failed.op: %s",
20516ff6b2fSAndreas Jaekel 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
20616ff6b2fSAndreas Jaekel 		zpf("  message: %s", ZEV_ERRSTR(rec));
20716ff6b2fSAndreas Jaekel 		znl();
20816ff6b2fSAndreas Jaekel 	} else {
209f2dd45e5SAndreas Jaekel 		printf("%s %s: failed_op=%s msg=%s\n",
210f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
21116ff6b2fSAndreas Jaekel 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
21216ff6b2fSAndreas Jaekel 		       ZEV_ERRSTR(rec));
21316ff6b2fSAndreas Jaekel 	}
214f2dd45e5SAndreas Jaekel }
215f2dd45e5SAndreas Jaekel 
216f2dd45e5SAndreas Jaekel static void
217888fea18SAndreas Jaekel zev_print_mark(char *buf)
218888fea18SAndreas Jaekel {
219888fea18SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
220888fea18SAndreas Jaekel 	time_t op_time = rec->op_time;
221888fea18SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
222888fea18SAndreas Jaekel 
22316ff6b2fSAndreas Jaekel 	if (verbose) {
22416ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
22516ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
22616ff6b2fSAndreas Jaekel 		zpf("  mark.id: %llu", rec->mark_id);
22716ff6b2fSAndreas Jaekel 		zpf("  payload.len: %llu", rec->payload_len);
22816ff6b2fSAndreas Jaekel 		if (rec->payload_len)
22916ff6b2fSAndreas Jaekel 			zev_print_mark_payload(rec);
23016ff6b2fSAndreas Jaekel 		znl();
23116ff6b2fSAndreas Jaekel 	} else {
232888fea18SAndreas Jaekel 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
23316ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
23416ff6b2fSAndreas Jaekel 		       rec->mark_id, rec->payload_len);
23516ff6b2fSAndreas Jaekel 	}
236888fea18SAndreas Jaekel }
237888fea18SAndreas Jaekel 
238888fea18SAndreas Jaekel static void
239f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf)
240f2dd45e5SAndreas Jaekel {
241f2dd45e5SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
242f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
243f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
244f2dd45e5SAndreas Jaekel 
24516ff6b2fSAndreas Jaekel 	if (verbose) {
24616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
24716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
24816ff6b2fSAndreas Jaekel 		zpf("  dataset: %s", ZEV_DATASET(rec));
24916ff6b2fSAndreas Jaekel 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
25016ff6b2fSAndreas Jaekel 		zpf("  remount: %s", rec->remount ? "true" : "false");
25116ff6b2fSAndreas Jaekel 		zev_print_inode_info("root", &rec->root);
25216ff6b2fSAndreas Jaekel 		znl();
25316ff6b2fSAndreas Jaekel 	} else {
25416ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
25516ff6b2fSAndreas Jaekel 		       "mountpoint='%s'\n",
256f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
257f2dd45e5SAndreas Jaekel 		       rec->guid,
258f2dd45e5SAndreas Jaekel 		       rec->remount ? "true" : "false",
259f2dd45e5SAndreas Jaekel 		       ZEV_DATASET(rec),
260f2dd45e5SAndreas Jaekel 		       ZEV_MOUNTPOINT(rec));
261f2dd45e5SAndreas Jaekel 	}
26216ff6b2fSAndreas Jaekel }
263f2dd45e5SAndreas Jaekel 
264f2dd45e5SAndreas Jaekel static void
265f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf)
266f2dd45e5SAndreas Jaekel {
267f2dd45e5SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
268f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
269f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
270f2dd45e5SAndreas Jaekel 
27116ff6b2fSAndreas Jaekel 	if (verbose) {
27216ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
27316ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
27416ff6b2fSAndreas Jaekel 		znl();
27516ff6b2fSAndreas Jaekel 	} else {
276f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
277f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
278f2dd45e5SAndreas Jaekel 		       rec->guid);
279f2dd45e5SAndreas Jaekel 	}
28016ff6b2fSAndreas Jaekel }
281f2dd45e5SAndreas Jaekel 
282f2dd45e5SAndreas Jaekel static void
283f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf)
284f2dd45e5SAndreas Jaekel {
285f2dd45e5SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
286f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
287f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
288f2dd45e5SAndreas Jaekel 
28916ff6b2fSAndreas Jaekel 	if (verbose) {
29016ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
29116ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
29212119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
29316ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
29416ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
29516ff6b2fSAndreas Jaekel 		znl();
29616ff6b2fSAndreas Jaekel 	} else {
297f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
298f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
299f2dd45e5SAndreas Jaekel 		       rec->guid,
300f2dd45e5SAndreas Jaekel 		       rec->offset,
301f2dd45e5SAndreas Jaekel 		       rec->length);
302f2dd45e5SAndreas Jaekel 	}
30316ff6b2fSAndreas Jaekel }
304f2dd45e5SAndreas Jaekel 
305f2dd45e5SAndreas Jaekel static void
306f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf)
307f2dd45e5SAndreas Jaekel {
308f2dd45e5SAndreas Jaekel 	zev_print_zvol_truncate(buf);
309f2dd45e5SAndreas Jaekel }
310f2dd45e5SAndreas Jaekel 
311f2dd45e5SAndreas Jaekel static void
312f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
313f2dd45e5SAndreas Jaekel {
314f2dd45e5SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
315f2dd45e5SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
316f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
317f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
318f2dd45e5SAndreas Jaekel 
31916ff6b2fSAndreas Jaekel 	if (verbose) {
32016ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
32116ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
32216ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
32316ff6b2fSAndreas Jaekel 		znl();
32416ff6b2fSAndreas Jaekel 	} else {
325f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
326f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
327f2dd45e5SAndreas Jaekel 		       rec->guid,
328f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
329f2dd45e5SAndreas Jaekel 	}
33016ff6b2fSAndreas Jaekel }
331f2dd45e5SAndreas Jaekel 
332f2dd45e5SAndreas Jaekel static void
333f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf)
334f2dd45e5SAndreas Jaekel {
335f2dd45e5SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
336f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
337f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
3382eabeab5SAndreas Jaekel 	zev_sig_t *sig;
3392eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
340f2dd45e5SAndreas Jaekel 
34116ff6b2fSAndreas Jaekel 	if (verbose) {
34216ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
34316ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
34412119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
34516ff6b2fSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
3462eabeab5SAndreas Jaekel 		sig = &rec->signature;
3472eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
3482eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
3492eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
35016ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
35112119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
35216ff6b2fSAndreas Jaekel 		znl();
35316ff6b2fSAndreas Jaekel 	} else {
35435d4e8ddSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
35535d4e8ddSAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
356f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
357f2dd45e5SAndreas Jaekel 		       rec->guid,
358f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
359f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
36035d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
361f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
362f2dd45e5SAndreas Jaekel 	}
36316ff6b2fSAndreas Jaekel }
364f2dd45e5SAndreas Jaekel 
365f2dd45e5SAndreas Jaekel static void
366f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf)
367f2dd45e5SAndreas Jaekel {
368f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
369f2dd45e5SAndreas Jaekel }
370f2dd45e5SAndreas Jaekel 
371f2dd45e5SAndreas Jaekel static void
372f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
373f2dd45e5SAndreas Jaekel {
374f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
375f2dd45e5SAndreas Jaekel }
376f2dd45e5SAndreas Jaekel 
377f2dd45e5SAndreas Jaekel static void
378f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf)
379f2dd45e5SAndreas Jaekel {
380f2dd45e5SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
381f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
382f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
383f2dd45e5SAndreas Jaekel 
38416ff6b2fSAndreas Jaekel 	if (verbose) {
38516ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
38616ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
38712119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
38816ff6b2fSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
38916ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
39012119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
39116ff6b2fSAndreas Jaekel 		znl();
39216ff6b2fSAndreas Jaekel 	} else {
39316ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
39416ff6b2fSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
395f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
396f2dd45e5SAndreas Jaekel 		       rec->guid,
397f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
39897dcf88dSAndreas Jaekel 		       rec->file.mtime,
399f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
400f2dd45e5SAndreas Jaekel 	}
40116ff6b2fSAndreas Jaekel }
402f2dd45e5SAndreas Jaekel 
403f2dd45e5SAndreas Jaekel static void
404f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf)
405f2dd45e5SAndreas Jaekel {
406f2dd45e5SAndreas Jaekel 	zev_print_znode_remove(buf);
407f2dd45e5SAndreas Jaekel }
408f2dd45e5SAndreas Jaekel 
409f2dd45e5SAndreas Jaekel static void
410f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf)
411f2dd45e5SAndreas Jaekel {
412f2dd45e5SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
413f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
414f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
415f2dd45e5SAndreas Jaekel 
41616ff6b2fSAndreas Jaekel 	if (verbose) {
41716ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
41816ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
41912119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
42016ff6b2fSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
42116ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
42212119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
42316ff6b2fSAndreas Jaekel 		znl();
42416ff6b2fSAndreas Jaekel 	} else {
425a01b300aSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
426a01b300aSAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
427f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
428f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
429f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
430a01b300aSAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
431f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
43216ff6b2fSAndreas Jaekel 	}
433f2dd45e5SAndreas Jaekel }
434f2dd45e5SAndreas Jaekel 
435f2dd45e5SAndreas Jaekel static void
436f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf)
437f2dd45e5SAndreas Jaekel {
438f2dd45e5SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
439f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
440f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
4412eabeab5SAndreas Jaekel 	zev_sig_t *sig;
4422eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
443f2dd45e5SAndreas Jaekel 
44416ff6b2fSAndreas Jaekel 	if (verbose) {
44516ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
44616ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
44712119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
44816ff6b2fSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
44916ff6b2fSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
4502eabeab5SAndreas Jaekel 		sig = &rec->signature;
4512eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
4522eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
4532eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
45416ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
45512119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
45616ff6b2fSAndreas Jaekel 		znl();
45716ff6b2fSAndreas Jaekel 	} else {
45816ff6b2fSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
45916ff6b2fSAndreas Jaekel 		       "name='%s' link='%s'\n",
460f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
461f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
462f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
463f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec),
464f2dd45e5SAndreas Jaekel 		       ZEV_LINK(rec));
465f2dd45e5SAndreas Jaekel 	}
46616ff6b2fSAndreas Jaekel }
467f2dd45e5SAndreas Jaekel 
468f2dd45e5SAndreas Jaekel static void
469f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf)
470f2dd45e5SAndreas Jaekel {
471f2dd45e5SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
472f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
473f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
474f2dd45e5SAndreas Jaekel 
47516ff6b2fSAndreas Jaekel 	if (verbose) {
47616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
47716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
47812119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
47916ff6b2fSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
48016ff6b2fSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
48116ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
48216ff6b2fSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
48316ff6b2fSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
48416ff6b2fSAndreas Jaekel 		znl();
48516ff6b2fSAndreas Jaekel 	} else {
48616ff6b2fSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
48716ff6b2fSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
48816ff6b2fSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
48916ff6b2fSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
490f2dd45e5SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
491f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
492f2dd45e5SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
493f2dd45e5SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
494f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
49535d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
49635d4e8ddSAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
49735d4e8ddSAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
498f2dd45e5SAndreas Jaekel 		       ZEV_SRCNAME(rec),
499f2dd45e5SAndreas Jaekel 		       ZEV_DSTNAME(rec));
500f2dd45e5SAndreas Jaekel 	}
50116ff6b2fSAndreas Jaekel }
502f2dd45e5SAndreas Jaekel 
503f2dd45e5SAndreas Jaekel static void
504f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf)
505f2dd45e5SAndreas Jaekel {
506f2dd45e5SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
507f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
508f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
509205ed6bfSAndreas Jaekel 	zev_sig_t *sig;
510205ed6bfSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
511205ed6bfSAndreas Jaekel 	int i;
512f2dd45e5SAndreas Jaekel 
513205ed6bfSAndreas Jaekel 	if (verbose) {
51416ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
51516ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
51612119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
51716ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
51816ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
51916ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
52016ff6b2fSAndreas Jaekel 		znl();
521205ed6bfSAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
522205ed6bfSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
523205ed6bfSAndreas Jaekel 			sig += i;
524205ed6bfSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
5252eabeab5SAndreas Jaekel 			zpf("  sig: level %d, offset %llu, value %s",
526205ed6bfSAndreas Jaekel 			    sig->level, sig->block_offset, sigval);
527205ed6bfSAndreas Jaekel 		}
52816ff6b2fSAndreas Jaekel 	} else {
52916ff6b2fSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
53016ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
53116ff6b2fSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
53216ff6b2fSAndreas Jaekel 		       rec->offset, rec->length);
533205ed6bfSAndreas Jaekel 	}
534f2dd45e5SAndreas Jaekel }
535f2dd45e5SAndreas Jaekel 
536f2dd45e5SAndreas Jaekel static void
537f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf)
538f2dd45e5SAndreas Jaekel {
539f2dd45e5SAndreas Jaekel 	zev_print_znode_write(buf);
540f2dd45e5SAndreas Jaekel }
541f2dd45e5SAndreas Jaekel 
542f2dd45e5SAndreas Jaekel static void
543f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf)
544f2dd45e5SAndreas Jaekel {
545f2dd45e5SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
546f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
547f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
548f2dd45e5SAndreas Jaekel 
54916ff6b2fSAndreas Jaekel 	if (verbose) {
55016ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
55116ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
55212119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
55316ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
55416ff6b2fSAndreas Jaekel 		znl();
55516ff6b2fSAndreas Jaekel 	} else {
55635d4e8ddSAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
557f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
55835d4e8ddSAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
559f2dd45e5SAndreas Jaekel 	}
56016ff6b2fSAndreas Jaekel }
561f2dd45e5SAndreas Jaekel 
562f2dd45e5SAndreas Jaekel static void
563f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf)
564f2dd45e5SAndreas Jaekel {
565f2dd45e5SAndreas Jaekel 	zev_print_znode_setattr(buf);
566f2dd45e5SAndreas Jaekel }
567f2dd45e5SAndreas Jaekel 
568f2dd45e5SAndreas Jaekel static void
569aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
570aafc540fSAndreas Jaekel {
571f2dd45e5SAndreas Jaekel 	int record_len;
572f2dd45e5SAndreas Jaekel 	int op;
573aafc540fSAndreas Jaekel 
574f2dd45e5SAndreas Jaekel 	record_len = *(uint32_t *)buf;
575f2dd45e5SAndreas Jaekel 	if (record_len != len) {
576f2dd45e5SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
577f2dd45e5SAndreas Jaekel 		        record_len, len);
578aafc540fSAndreas Jaekel 		exit(1);
579aafc540fSAndreas Jaekel 	}
580f2dd45e5SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
581aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
582f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
583aafc540fSAndreas Jaekel 		exit(1);
584aafc540fSAndreas Jaekel 	}
585f2dd45e5SAndreas Jaekel 	switch (op) {
586f2dd45e5SAndreas Jaekel 	case ZEV_OP_ERROR:
587f2dd45e5SAndreas Jaekel 		zev_print_error(buf);
588aafc540fSAndreas Jaekel 		break;
589888fea18SAndreas Jaekel 	case ZEV_OP_MARK:
590888fea18SAndreas Jaekel 		zev_print_mark(buf);
591888fea18SAndreas Jaekel 		break;
592f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
593f2dd45e5SAndreas Jaekel 		zev_print_zfs_mount(buf);
594aafc540fSAndreas Jaekel 		break;
595f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
596f2dd45e5SAndreas Jaekel 		zev_print_zfs_umount(buf);
597aafc540fSAndreas Jaekel 		break;
598f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
599f2dd45e5SAndreas Jaekel 		zev_print_zvol_truncate(buf);
600aafc540fSAndreas Jaekel 		break;
601f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
602f2dd45e5SAndreas Jaekel 		zev_print_zvol_write(buf);
603f2dd45e5SAndreas Jaekel 		break;
604f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
605f2dd45e5SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
606f2dd45e5SAndreas Jaekel 		break;
607f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
608f2dd45e5SAndreas Jaekel 		zev_print_znode_create(buf);
609f2dd45e5SAndreas Jaekel 		break;
610f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
611f2dd45e5SAndreas Jaekel 		zev_print_znode_mkdir(buf);
612f2dd45e5SAndreas Jaekel 		break;
613f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
614f2dd45e5SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
615f2dd45e5SAndreas Jaekel 		break;
616f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
617f2dd45e5SAndreas Jaekel 		zev_print_znode_remove(buf);
618f2dd45e5SAndreas Jaekel 		break;
619f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
620f2dd45e5SAndreas Jaekel 		zev_print_znode_rmdir(buf);
621f2dd45e5SAndreas Jaekel 		break;
622f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
623f2dd45e5SAndreas Jaekel 		zev_print_znode_link(buf);
624f2dd45e5SAndreas Jaekel 		break;
625f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
626f2dd45e5SAndreas Jaekel 		zev_print_znode_symlink(buf);
627f2dd45e5SAndreas Jaekel 		break;
628f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
629f2dd45e5SAndreas Jaekel 		zev_print_znode_rename(buf);
630f2dd45e5SAndreas Jaekel 		break;
631f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
632f2dd45e5SAndreas Jaekel 		zev_print_znode_write(buf);
633f2dd45e5SAndreas Jaekel 		break;
634f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
635f2dd45e5SAndreas Jaekel 		zev_print_znode_truncate(buf);
636f2dd45e5SAndreas Jaekel 		break;
637f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
638f2dd45e5SAndreas Jaekel 		zev_print_znode_setattr(buf);
639f2dd45e5SAndreas Jaekel 		break;
640f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
641f2dd45e5SAndreas Jaekel 		zev_print_znode_acl(buf);
642aafc540fSAndreas Jaekel 		break;
643aafc540fSAndreas Jaekel 	default:
644f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
645aafc540fSAndreas Jaekel 		exit(1);
646aafc540fSAndreas Jaekel 	}
647aafc540fSAndreas Jaekel }
648aafc540fSAndreas Jaekel 
649add9520fSAndreas Jaekel static int
6506a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
651a18c35b9SAndreas Jaekel {
652a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
653a18c35b9SAndreas Jaekel 	int ret;
654aafc540fSAndreas Jaekel 	char buf[4096];
655d979f56cSAndreas Jaekel 	zev_event_t *ev;
656d979f56cSAndreas Jaekel 	int off = 0;
657add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
658add9520fSAndreas Jaekel 	int q_fd;
659add9520fSAndreas Jaekel 
6606a6a51eeSAndreas Jaekel 	if (create_tmp_queue) {
661add9520fSAndreas Jaekel 		aq.zev_max_queue_len = 0;
662add9520fSAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
663add9520fSAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
664add9520fSAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
665add9520fSAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
666add9520fSAndreas Jaekel 
667add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
668add9520fSAndreas Jaekel 			perror("adding temporary queue failed");
669add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
670add9520fSAndreas Jaekel 		}
671add9520fSAndreas Jaekel 
6726a6a51eeSAndreas Jaekel 		snprintf(buf, sizeof(buf),
6736a6a51eeSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
674add9520fSAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
675add9520fSAndreas Jaekel 		if (q_fd < 0) {
676add9520fSAndreas Jaekel 			perror("opening queue device failed");
677add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
678add9520fSAndreas Jaekel 		}
6796a6a51eeSAndreas Jaekel 	} else {
6806a6a51eeSAndreas Jaekel 		q_fd = fd;
6816a6a51eeSAndreas Jaekel 	}
682add9520fSAndreas Jaekel 
683a18c35b9SAndreas Jaekel 	while (1) {
684add9520fSAndreas Jaekel 		pfd[0].fd = q_fd;
685a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
686a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
687a18c35b9SAndreas Jaekel 		if (ret < 0) {
688a18c35b9SAndreas Jaekel 			perror("poll failed");
6896a6a51eeSAndreas Jaekel 			close(q_fd);
690add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
691a18c35b9SAndreas Jaekel 		}
692a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
693a18c35b9SAndreas Jaekel 			continue;
694a18c35b9SAndreas Jaekel 		/* data available */
695add9520fSAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
696a18c35b9SAndreas Jaekel 		if (ret < 0) {
697a18c35b9SAndreas Jaekel 			perror("read failed");
6986a6a51eeSAndreas Jaekel 			close(q_fd);
699add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
700a18c35b9SAndreas Jaekel 		}
701a18c35b9SAndreas Jaekel 		if (ret == 0)
702a18c35b9SAndreas Jaekel 			continue;
703d979f56cSAndreas Jaekel 		while (ret > off) {
704d979f56cSAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
705d979f56cSAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
706d979f56cSAndreas Jaekel 			off += ev->header.record_len;
707d979f56cSAndreas Jaekel 		}
708149d0affSAndreas Jaekel 		off = 0;
709a18c35b9SAndreas Jaekel 	}
7106a6a51eeSAndreas Jaekel 	if (create_tmp_queue)
711add9520fSAndreas Jaekel 		close(q_fd);
712add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
713a18c35b9SAndreas Jaekel }
714a18c35b9SAndreas Jaekel 
715a18c35b9SAndreas Jaekel static void
716a18c35b9SAndreas Jaekel usage(char *progname)
717a18c35b9SAndreas Jaekel {
718add9520fSAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
719add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
720add9520fSAndreas Jaekel 	fprintf(stderr, " Status information:\n");
721a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
722a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
723add9520fSAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
724add9520fSAndreas Jaekel 	        "information\n");
725b690436dSAndreas Jaekel 	fprintf(stderr, "   -T <interval> <cnt>  zevstat mode\n");
726f432e238SAndreas Jaekel 	fprintf(stderr, "   -R <base filename>   zevreport mode\n");
727add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
728add9520fSAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
729add9520fSAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
730add9520fSAndreas Jaekel 	        "length\n");
731add9520fSAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
732add9520fSAndreas Jaekel 	        "this pool\n");
733a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
734add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
735add9520fSAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
736add9520fSAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
7376a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
7386a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
739add9520fSAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
740add9520fSAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
741add9520fSAndreas Jaekel 	        "(default)\n");
742add9520fSAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
743add9520fSAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
7446a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
745add9520fSAndreas Jaekel 	        "length\n");
746add9520fSAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
747add9520fSAndreas Jaekel 	        "throttle\n");
748add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
749add9520fSAndreas Jaekel 	fprintf(stderr, " Other options:\n");
750add9520fSAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
751add9520fSAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
7526a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
7536a6a51eeSAndreas Jaekel 		"queue name\n");
754888fea18SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
75542110aacSAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
75642110aacSAndreas Jaekel 		"checksums\n");
75716ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
758205ed6bfSAndreas Jaekel 	        "for some operations\n");
75916ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
76016ff6b2fSAndreas Jaekel 	        "one event per line\n");
761a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
762a18c35b9SAndreas Jaekel }
763a18c35b9SAndreas Jaekel 
76450da9edeSAndreas Jaekel static void
76550da9edeSAndreas Jaekel zevstat_usage(char *progname)
76650da9edeSAndreas Jaekel {
76750da9edeSAndreas Jaekel 	fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname);
76850da9edeSAndreas Jaekel 	fprintf(stderr, "   -v   verbose, show counters for all event types\n");
76950da9edeSAndreas Jaekel 	exit (EXIT_FAILURE);
77050da9edeSAndreas Jaekel }
77150da9edeSAndreas Jaekel 
772f432e238SAndreas Jaekel static void
773f432e238SAndreas Jaekel zevreport_usage(char *progname)
774f432e238SAndreas Jaekel {
775f432e238SAndreas Jaekel 	fprintf(stderr, "usage: %s <output base filename>\n", progname);
776f432e238SAndreas Jaekel 	exit (EXIT_FAILURE);
777f432e238SAndreas Jaekel }
778f432e238SAndreas Jaekel 
779a18c35b9SAndreas Jaekel static int
7806a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
781a18c35b9SAndreas Jaekel {
782add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
783add9520fSAndreas Jaekel 	int namelen;
784a18c35b9SAndreas Jaekel 
785add9520fSAndreas Jaekel 	namelen = strlen(arg);
786add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
787add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
788a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
789a18c35b9SAndreas Jaekel 	}
790add9520fSAndreas Jaekel 
791add9520fSAndreas Jaekel 	aq.zev_namelen = namelen;
792add9520fSAndreas Jaekel 	strcpy(aq.zev_name, arg);
793*c99a1a25SAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT | ZEV_FL_INITIALLY_EMPTY;
7946a6a51eeSAndreas Jaekel 	if (blocking) {
7956a6a51eeSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
7966a6a51eeSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
7976a6a51eeSAndreas Jaekel 	} else {
798add9520fSAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
7996a6a51eeSAndreas Jaekel 	}
800add9520fSAndreas Jaekel 
801add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
802add9520fSAndreas Jaekel 		perror("adding queue failed");
803a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
804a18c35b9SAndreas Jaekel 	}
805a18c35b9SAndreas Jaekel 	return (0);
806a18c35b9SAndreas Jaekel }
807a18c35b9SAndreas Jaekel 
808a18c35b9SAndreas Jaekel static int
809add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg)
810fec460f8SAndreas Jaekel {
811add9520fSAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
812add9520fSAndreas Jaekel 	int namelen;
813fec460f8SAndreas Jaekel 
814add9520fSAndreas Jaekel 	namelen = strlen(arg);
815add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
816add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
817fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
818fec460f8SAndreas Jaekel 	}
819add9520fSAndreas Jaekel 
8206a6a51eeSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
8216a6a51eeSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
822add9520fSAndreas Jaekel 
823add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
824add9520fSAndreas Jaekel 		perror("removing queue failed");
825add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
826add9520fSAndreas Jaekel 	}
827add9520fSAndreas Jaekel 	return (0);
828add9520fSAndreas Jaekel }
829add9520fSAndreas Jaekel 
830add9520fSAndreas Jaekel static int
831add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
832add9520fSAndreas Jaekel {
833add9520fSAndreas Jaekel 	uint64_t maxqueuelen;
834add9520fSAndreas Jaekel 
835174dc952SAndreas Jaekel 	if (!arg) {
836174dc952SAndreas Jaekel 		fprintf(stderr, "missing queue length parameter\n");
837174dc952SAndreas Jaekel 		return (EXIT_FAILURE);
838174dc952SAndreas Jaekel 	}
839174dc952SAndreas Jaekel 
840add9520fSAndreas Jaekel 	errno = 0;
841add9520fSAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
842add9520fSAndreas Jaekel 	if (errno) {
843add9520fSAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
844add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
845add9520fSAndreas Jaekel 	}
846add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
847add9520fSAndreas Jaekel 		perror("setting max queue length failed");
848fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
849fec460f8SAndreas Jaekel 	}
850fec460f8SAndreas Jaekel 	return (0);
851fec460f8SAndreas Jaekel }
852fec460f8SAndreas Jaekel 
853fec460f8SAndreas Jaekel static int
854a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
855a18c35b9SAndreas Jaekel {
856a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
857a18c35b9SAndreas Jaekel 	int len;
858a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
859a18c35b9SAndreas Jaekel 	len = strlen(poolname);
860a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
861a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
862a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
863a18c35b9SAndreas Jaekel 	}
864a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
865a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
866a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
867a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
868a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
869a18c35b9SAndreas Jaekel 	}
870a18c35b9SAndreas Jaekel 	return (0);
871a18c35b9SAndreas Jaekel }
872a18c35b9SAndreas Jaekel 
873a18c35b9SAndreas Jaekel int
874a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
875a18c35b9SAndreas Jaekel {
876a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
877a18c35b9SAndreas Jaekel }
878a18c35b9SAndreas Jaekel 
879a18c35b9SAndreas Jaekel int
880a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
881a18c35b9SAndreas Jaekel {
882a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
883a18c35b9SAndreas Jaekel }
884a18c35b9SAndreas Jaekel 
885888fea18SAndreas Jaekel static int
886add9520fSAndreas Jaekel zev_debug_info(int fd)
887add9520fSAndreas Jaekel {
888add9520fSAndreas Jaekel 	zev_ioctl_debug_info_t di;
889add9520fSAndreas Jaekel 
890add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
891add9520fSAndreas Jaekel 		perror("getting zev debug info failed");
892add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
893add9520fSAndreas Jaekel 	}
894add9520fSAndreas Jaekel 
895add9520fSAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
896205ed6bfSAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
897205ed6bfSAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
898205ed6bfSAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
899add9520fSAndreas Jaekel 	return 0;
900add9520fSAndreas Jaekel }
901add9520fSAndreas Jaekel 
902add9520fSAndreas Jaekel static int
903888fea18SAndreas Jaekel zev_mark(int fd, char *arg)
904888fea18SAndreas Jaekel {
905888fea18SAndreas Jaekel 	zev_ioctl_mark_t *mark;
906888fea18SAndreas Jaekel 	uint64_t guid;
907888fea18SAndreas Jaekel 	int len;
908888fea18SAndreas Jaekel 	char *p;
909888fea18SAndreas Jaekel 
910888fea18SAndreas Jaekel 	p = strchr(arg, ':');
911888fea18SAndreas Jaekel 	if (!p) {
912888fea18SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
913888fea18SAndreas Jaekel 		        "e.g. '123:hello'\n");
914888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
915888fea18SAndreas Jaekel 	}
916888fea18SAndreas Jaekel 	*p = '\n';
917888fea18SAndreas Jaekel 	p++;
918888fea18SAndreas Jaekel 
919888fea18SAndreas Jaekel 	errno = 0;
920add9520fSAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
921888fea18SAndreas Jaekel 	if (errno) {
922888fea18SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
923888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
924888fea18SAndreas Jaekel 	}
925888fea18SAndreas Jaekel 
926888fea18SAndreas Jaekel 	len = strlen(p);
927888fea18SAndreas Jaekel 
928888fea18SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
929888fea18SAndreas Jaekel 	if (!mark) {
930888fea18SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
931888fea18SAndreas Jaekel 		        strerror(errno));
932888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
933888fea18SAndreas Jaekel 	}
934888fea18SAndreas Jaekel 	mark->zev_guid = guid;
935888fea18SAndreas Jaekel 	mark->zev_mark_id = 0;
936888fea18SAndreas Jaekel 	mark->zev_payload_len = len;
937888fea18SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
938888fea18SAndreas Jaekel 
939888fea18SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
940888fea18SAndreas Jaekel 		perror("queueing mark failed");
941888fea18SAndreas Jaekel 		return (EXIT_FAILURE);
942888fea18SAndreas Jaekel 	}
943888fea18SAndreas Jaekel 
944888fea18SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
945888fea18SAndreas Jaekel 	return (0);
946888fea18SAndreas Jaekel }
947888fea18SAndreas Jaekel 
948add9520fSAndreas Jaekel static int
949add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
950add9520fSAndreas Jaekel {
951add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
952add9520fSAndreas Jaekel 
9536a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9546a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
955add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
956add9520fSAndreas Jaekel 		return EXIT_FAILURE;
957add9520fSAndreas Jaekel 	}
9586a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
959add9520fSAndreas Jaekel 
960add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
961add9520fSAndreas Jaekel 		perror("getting queue properties failed");
962add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
963add9520fSAndreas Jaekel 	}
964add9520fSAndreas Jaekel 	if (block) {
965add9520fSAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
966add9520fSAndreas Jaekel 	} else {
967add9520fSAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
968add9520fSAndreas Jaekel 	}
969add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
970add9520fSAndreas Jaekel 		perror("setting queue properties failed");
971add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
972add9520fSAndreas Jaekel 	}
973add9520fSAndreas Jaekel 	return (0);
974add9520fSAndreas Jaekel }
975add9520fSAndreas Jaekel 
976add9520fSAndreas Jaekel static int
977add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
978add9520fSAndreas Jaekel {
979add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
980add9520fSAndreas Jaekel 
981add9520fSAndreas Jaekel 	if (!len) {
982add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
983add9520fSAndreas Jaekel 		return EXIT_FAILURE;
984add9520fSAndreas Jaekel 	}
985add9520fSAndreas Jaekel 
9866a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9876a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
988add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
989add9520fSAndreas Jaekel 		return EXIT_FAILURE;
990add9520fSAndreas Jaekel 	}
9916a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
992add9520fSAndreas Jaekel 
993add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
994add9520fSAndreas Jaekel 		perror("getting queue properties failed");
995add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
996add9520fSAndreas Jaekel 	}
997add9520fSAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
998add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
999add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
1000add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1001add9520fSAndreas Jaekel 	}
1002add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
1003add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
1004add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1005add9520fSAndreas Jaekel 	}
1006add9520fSAndreas Jaekel 
1007add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1008add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1009add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1010add9520fSAndreas Jaekel 	}
1011add9520fSAndreas Jaekel 	return (0);
1012add9520fSAndreas Jaekel }
1013add9520fSAndreas Jaekel 
1014add9520fSAndreas Jaekel static int
1015add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
1016add9520fSAndreas Jaekel {
1017add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1018add9520fSAndreas Jaekel 
1019add9520fSAndreas Jaekel 	if (!len) {
1020add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
1021add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1022add9520fSAndreas Jaekel 	}
1023add9520fSAndreas Jaekel 
10246a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10256a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1026add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1027add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1028add9520fSAndreas Jaekel 	}
10296a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1030add9520fSAndreas Jaekel 
1031add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1032add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1033add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1034add9520fSAndreas Jaekel 	}
1035add9520fSAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
1036add9520fSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
1037add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
1038add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1039add9520fSAndreas Jaekel 	}
10406a6a51eeSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
1041add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
1042add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1043add9520fSAndreas Jaekel 	}
1044add9520fSAndreas Jaekel 
1045add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1046add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1047add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1048add9520fSAndreas Jaekel 	}
1049add9520fSAndreas Jaekel 	return (0);
1050add9520fSAndreas Jaekel }
1051add9520fSAndreas Jaekel 
1052add9520fSAndreas Jaekel static int
1053add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg)
1054add9520fSAndreas Jaekel {
1055add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1056add9520fSAndreas Jaekel 
10576a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10586a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1059add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1060add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1061add9520fSAndreas Jaekel 	}
10626a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1063add9520fSAndreas Jaekel 
1064add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1065add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1066add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1067add9520fSAndreas Jaekel 	}
1068add9520fSAndreas Jaekel 
1069add9520fSAndreas Jaekel 	printf("queue        : %s\n", arg);
1070add9520fSAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1071add9520fSAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1072add9520fSAndreas Jaekel 	printf("persistent   : %s\n",
1073add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1074add9520fSAndreas Jaekel 	printf("blocking     : %s\n",
1075add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1076add9520fSAndreas Jaekel 
1077add9520fSAndreas Jaekel 	return (0);
1078add9520fSAndreas Jaekel }
1079add9520fSAndreas Jaekel 
1080add9520fSAndreas Jaekel static int
1081add9520fSAndreas Jaekel zev_list_queues(int fd)
1082add9520fSAndreas Jaekel {
1083add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1084add9520fSAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1085add9520fSAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1086add9520fSAndreas Jaekel 	uint64_t	i;
1087add9520fSAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1088add9520fSAndreas Jaekel 
1089add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1090add9520fSAndreas Jaekel 		perror("getting queue list failed");
1091add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1092add9520fSAndreas Jaekel 	}
1093add9520fSAndreas Jaekel 
1094add9520fSAndreas Jaekel 	printf("Name                                     Size       "
1095add9520fSAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
1096add9520fSAndreas Jaekel 
1097add9520fSAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1098add9520fSAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1099add9520fSAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1100add9520fSAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1101add9520fSAndreas Jaekel 
11026a6a51eeSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
11036a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11046a6a51eeSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
11056a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1106add9520fSAndreas Jaekel 
1107add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1108add9520fSAndreas Jaekel 			if (errno == ENOENT)
1109add9520fSAndreas Jaekel 				continue;
1110add9520fSAndreas Jaekel 			perror("getting queue properties failed");
1111add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1112add9520fSAndreas Jaekel 		}
1113add9520fSAndreas Jaekel 
11146a6a51eeSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
11156a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11166a6a51eeSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
11176a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1118add9520fSAndreas Jaekel 
1119add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1120add9520fSAndreas Jaekel 			if (errno == ENOENT)
1121add9520fSAndreas Jaekel 				continue;
1122add9520fSAndreas Jaekel 			perror("getting statistics data failed");
1123add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1124add9520fSAndreas Jaekel 		}
1125add9520fSAndreas Jaekel 
1126add9520fSAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
1127add9520fSAndreas Jaekel 		       " %-3s %-3s\n",
1128add9520fSAndreas Jaekel 			name,
1129add9520fSAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1130add9520fSAndreas Jaekel 			gqp.zev_max_queue_len,
1131add9520fSAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
1132add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1133add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1134add9520fSAndreas Jaekel 				 "yes" : "no");
1135add9520fSAndreas Jaekel 	}
1136add9520fSAndreas Jaekel 
1137add9520fSAndreas Jaekel 	return (0);
1138add9520fSAndreas Jaekel }
1139add9520fSAndreas Jaekel 
114042110aacSAndreas Jaekel static int
114142110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename)
114242110aacSAndreas Jaekel {
114342110aacSAndreas Jaekel 	int fd;
114442110aacSAndreas Jaekel 	offset_t off;
114542110aacSAndreas Jaekel 	offset_t data;
114642110aacSAndreas Jaekel 	zev_sig_t *sig;
114742110aacSAndreas Jaekel 	char *buf;
114842110aacSAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
114942110aacSAndreas Jaekel 	int i;
115042110aacSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
115142110aacSAndreas Jaekel 	int buf_size;
115242110aacSAndreas Jaekel 
115342110aacSAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
115442110aacSAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
115542110aacSAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
115642110aacSAndreas Jaekel 	if (!buf) {
115742110aacSAndreas Jaekel 		perror("can't allocate checksum buffer");
115842110aacSAndreas Jaekel 		return (EXIT_FAILURE);
115942110aacSAndreas Jaekel 	}
116042110aacSAndreas Jaekel 
116142110aacSAndreas Jaekel 	fd = open(filename, O_RDONLY);
116242110aacSAndreas Jaekel 	if (fd < 0) {
116342110aacSAndreas Jaekel 		perror("can't open file");
116442110aacSAndreas Jaekel 		return (EXIT_FAILURE);
116542110aacSAndreas Jaekel 	}
116642110aacSAndreas Jaekel 
116742110aacSAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
116842110aacSAndreas Jaekel 	gs->zev_fd = fd;
116942110aacSAndreas Jaekel 	gs->zev_bufsize = buf_size;
117042110aacSAndreas Jaekel 
117142110aacSAndreas Jaekel 	off = 0;
117242110aacSAndreas Jaekel 	data = 0;
117342110aacSAndreas Jaekel 	while (1) {
117442110aacSAndreas Jaekel 		errno = 0;
117542110aacSAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
117642110aacSAndreas Jaekel 		if (data < 0) {
117742110aacSAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
117842110aacSAndreas Jaekel 				break;
117942110aacSAndreas Jaekel 			perror("llseek failed");
118042110aacSAndreas Jaekel 			goto err;
118142110aacSAndreas Jaekel 		}
118242110aacSAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
118342110aacSAndreas Jaekel 		off = data + ZEV_L1_SIZE;
118442110aacSAndreas Jaekel 
118542110aacSAndreas Jaekel 		gs->zev_offset = data;
118642110aacSAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
118742110aacSAndreas Jaekel 
118842110aacSAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
118942110aacSAndreas Jaekel 			perror("ioctl to get signatures failed");
119042110aacSAndreas Jaekel 			goto err;
119142110aacSAndreas Jaekel 		}
119242110aacSAndreas Jaekel 
119342110aacSAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
119442110aacSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
119542110aacSAndreas Jaekel 			sig += i;
119642110aacSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
119742110aacSAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
119842110aacSAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
119942110aacSAndreas Jaekel 		}
120042110aacSAndreas Jaekel 	}
120142110aacSAndreas Jaekel 
120242110aacSAndreas Jaekel 	free(buf);
120342110aacSAndreas Jaekel 	close(fd);
120442110aacSAndreas Jaekel 	return 0;
120542110aacSAndreas Jaekel err:
120642110aacSAndreas Jaekel 	free(buf);
120742110aacSAndreas Jaekel 	close(fd);
120842110aacSAndreas Jaekel 	return (EXIT_FAILURE);
120942110aacSAndreas Jaekel }
121042110aacSAndreas Jaekel 
1211b690436dSAndreas Jaekel typedef struct zevstat {
1212b690436dSAndreas Jaekel 	uint64_t	ns_start;
1213b690436dSAndreas Jaekel 	uint64_t	events[ZEV_OP_MIN + ZEV_OP_MAX];
1214b690436dSAndreas Jaekel 	uint64_t	guids;
1215b690436dSAndreas Jaekel 	uint64_t	total_events;
1216b690436dSAndreas Jaekel 	uint64_t	total_guids;
1217b690436dSAndreas Jaekel 	avl_tree_t	guids_interval;
1218b690436dSAndreas Jaekel 	avl_tree_t	guids_runtime;
1219b690436dSAndreas Jaekel } zevstat_t;
1220b690436dSAndreas Jaekel 
1221b690436dSAndreas Jaekel typedef struct zev_guidtrack_t {
1222b690436dSAndreas Jaekel 	uint64_t	guid;
1223b690436dSAndreas Jaekel 	avl_node_t	avl_interval;
1224b690436dSAndreas Jaekel 	avl_node_t	avl_runtime;
1225b690436dSAndreas Jaekel } zev_guidtrack_t;
1226b690436dSAndreas Jaekel 
1227b690436dSAndreas Jaekel zevstat_t zevstat;
1228b690436dSAndreas Jaekel 
1229b690436dSAndreas Jaekel static void
1230b690436dSAndreas Jaekel zev_eventstat(char *buf, int len)
1231b690436dSAndreas Jaekel {
1232b690436dSAndreas Jaekel 	zev_header_t *rec = (zev_header_t *)buf;
1233b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1234b690436dSAndreas Jaekel 	zev_guidtrack_t *gt_int;
1235b690436dSAndreas Jaekel 	zev_guidtrack_t to_find;
1236b690436dSAndreas Jaekel 	avl_index_t where;
1237b690436dSAndreas Jaekel 
1238b690436dSAndreas Jaekel 	zevstat.total_events++;
1239b690436dSAndreas Jaekel 	zevstat.events[rec->op]++;
1240b690436dSAndreas Jaekel 
1241b690436dSAndreas Jaekel 	to_find.guid = rec->guid;
1242b690436dSAndreas Jaekel 	gt = avl_find(&zevstat.guids_runtime, &to_find, &where);
1243b690436dSAndreas Jaekel 	if (!gt) {
1244b690436dSAndreas Jaekel 		gt = malloc(sizeof(*gt));
1245b690436dSAndreas Jaekel 		if (!gt) {
1246b690436dSAndreas Jaekel 			perror("can't get guid tracking record");
1247b690436dSAndreas Jaekel 			exit (EXIT_FAILURE);
1248b690436dSAndreas Jaekel 		}
1249b690436dSAndreas Jaekel 		gt->guid = rec->guid;
1250b690436dSAndreas Jaekel 		avl_insert(&zevstat.guids_runtime, gt, where);
1251b690436dSAndreas Jaekel 	}
1252b690436dSAndreas Jaekel 	gt_int = avl_find(&zevstat.guids_interval, &to_find, &where);
1253b690436dSAndreas Jaekel 	if (!gt_int)
1254b690436dSAndreas Jaekel 		avl_insert(&zevstat.guids_interval, gt, where);
1255b690436dSAndreas Jaekel }
1256b690436dSAndreas Jaekel 
1257b690436dSAndreas Jaekel static void
1258f432e238SAndreas Jaekel zev_eventstat_interval(FILE *out)
1259b690436dSAndreas Jaekel {
1260b690436dSAndreas Jaekel 	uint64_t events;
1261b690436dSAndreas Jaekel 	int i;
1262b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1263b690436dSAndreas Jaekel 
1264b690436dSAndreas Jaekel 	events = 0;
1265b690436dSAndreas Jaekel 	for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) {
1266b690436dSAndreas Jaekel 		events += zevstat.events[i];
1267b690436dSAndreas Jaekel 	}
1268b690436dSAndreas Jaekel 
1269b690436dSAndreas Jaekel 	if (verbose) {
1270f432e238SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu  ",
1271b690436dSAndreas Jaekel 		        time(NULL),
1272b690436dSAndreas Jaekel 		        events,
1273b690436dSAndreas Jaekel 		        zevstat.total_events,
1274b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
1275b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
1276b690436dSAndreas Jaekel 		for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++)
1277f432e238SAndreas Jaekel 			fprintf(out, "%6llu ", zevstat.events[i]);
1278f432e238SAndreas Jaekel 		fprintf(out, "\n");
1279b690436dSAndreas Jaekel 	} else {
1280f432e238SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu\n",
1281b690436dSAndreas Jaekel 		        time(NULL),
1282b690436dSAndreas Jaekel 		        events,
1283b690436dSAndreas Jaekel 		        zevstat.total_events,
1284b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
1285b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
1286b690436dSAndreas Jaekel 	}
1287b690436dSAndreas Jaekel 	memset(&zevstat.events, 0, sizeof(zevstat.events));
1288b690436dSAndreas Jaekel 	zevstat.guids = 0;
1289b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
1290b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
1291f432e238SAndreas Jaekel 	fflush(out);
1292b690436dSAndreas Jaekel }
1293b690436dSAndreas Jaekel 
1294b690436dSAndreas Jaekel static int
1295b690436dSAndreas Jaekel zev_evcompar(const void *a, const void *b)
1296b690436dSAndreas Jaekel {
1297b690436dSAndreas Jaekel 	const zev_guidtrack_t *ga = a;
1298b690436dSAndreas Jaekel 	const zev_guidtrack_t *gb = b;
1299b690436dSAndreas Jaekel 
1300b690436dSAndreas Jaekel 	if (ga->guid > gb->guid)
1301b690436dSAndreas Jaekel 		return 1;
1302b690436dSAndreas Jaekel 	if (ga->guid < gb->guid)
1303b690436dSAndreas Jaekel 		return -1;
1304b690436dSAndreas Jaekel 	return 0;
1305b690436dSAndreas Jaekel }
1306b690436dSAndreas Jaekel 
1307b690436dSAndreas Jaekel static int
1308f432e238SAndreas Jaekel zev_zevstat(int fd, char *s_interval, char *s_count, char *outfile)
1309b690436dSAndreas Jaekel {
1310b690436dSAndreas Jaekel 	uint64_t interval = 1000;
1311b690436dSAndreas Jaekel 	uint64_t ms;
1312b690436dSAndreas Jaekel 	uint64_t t_until;
1313b690436dSAndreas Jaekel 	uint64_t t_now;
1314b690436dSAndreas Jaekel 	int cnt = -1;
1315b690436dSAndreas Jaekel 	struct pollfd pfd[1];
1316b690436dSAndreas Jaekel 	int ret;
1317b690436dSAndreas Jaekel 	char buf[4096];
1318b690436dSAndreas Jaekel 	zev_event_t *ev;
1319b690436dSAndreas Jaekel 	int off = 0;
1320b690436dSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
1321b690436dSAndreas Jaekel 	int q_fd;
1322b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1323f432e238SAndreas Jaekel 	FILE *out = stdout;
1324f432e238SAndreas Jaekel 	struct stat st;
1325f432e238SAndreas Jaekel 	char filename[MAXPATHLEN];
1326f432e238SAndreas Jaekel 	int retry;
1327f432e238SAndreas Jaekel 
1328f432e238SAndreas Jaekel 	if (outfile) {
1329f432e238SAndreas Jaekel 		retry = 0;
1330f432e238SAndreas Jaekel 		strncpy(filename, outfile, sizeof(filename));
1331f432e238SAndreas Jaekel 		while (stat(filename, &st) == 0) {
1332f432e238SAndreas Jaekel 			/* file exists */
1333f432e238SAndreas Jaekel 			snprintf(filename, sizeof(filename),
1334f432e238SAndreas Jaekel 			         "%s.%d", outfile, retry);
1335f432e238SAndreas Jaekel 			retry++;
1336f432e238SAndreas Jaekel 		}
1337f432e238SAndreas Jaekel 		out = fopen(filename, "wb+");
1338f432e238SAndreas Jaekel 		if (!out) {
1339f432e238SAndreas Jaekel 			perror("opening output file failed");
1340f432e238SAndreas Jaekel 			return (EXIT_FAILURE);
1341f432e238SAndreas Jaekel 		}
1342f432e238SAndreas Jaekel 	}
1343b690436dSAndreas Jaekel 
1344b690436dSAndreas Jaekel 	memset(&zevstat, 0, sizeof(zevstat));
1345b690436dSAndreas Jaekel 	avl_create(&zevstat.guids_runtime, zev_evcompar,
1346b690436dSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
1347b690436dSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_runtime));
1348b690436dSAndreas Jaekel 	avl_create(&zevstat.guids_interval, zev_evcompar,
1349b690436dSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
1350b690436dSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_interval));
1351b690436dSAndreas Jaekel 
135219695134SAndreas Jaekel 	if (s_interval) {
1353b690436dSAndreas Jaekel 		interval = atol(s_interval);
1354b690436dSAndreas Jaekel 		if (interval == 0) {
1355b690436dSAndreas Jaekel 			fprintf(stderr, "invalid interval.\n");
1356b690436dSAndreas Jaekel 			return (EXIT_FAILURE);
1357b690436dSAndreas Jaekel 		}
1358b690436dSAndreas Jaekel 		interval *= 1000;
135919695134SAndreas Jaekel 	}
1360b690436dSAndreas Jaekel 	if (s_count) {
1361b690436dSAndreas Jaekel 		cnt = atol(s_count);
1362b690436dSAndreas Jaekel 		if (interval == 0) {
1363b690436dSAndreas Jaekel 			fprintf(stderr, "invalid count.\n");
1364b690436dSAndreas Jaekel 			return (EXIT_FAILURE);
1365b690436dSAndreas Jaekel 		}
1366b690436dSAndreas Jaekel 	}
1367b690436dSAndreas Jaekel 
1368b690436dSAndreas Jaekel 	aq.zev_max_queue_len = 1024 * 1024;
1369*c99a1a25SAndreas Jaekel 	aq.zev_flags = ZEV_FL_INITIALLY_EMPTY;
1370b690436dSAndreas Jaekel 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
1371b690436dSAndreas Jaekel 		 "zevstat.%ld.%ld", time(NULL), getpid());
1372b690436dSAndreas Jaekel 	aq.zev_namelen = strlen(aq.zev_name);
1373b690436dSAndreas Jaekel 
1374b690436dSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
1375b690436dSAndreas Jaekel 		perror("adding temporary queue failed");
1376b690436dSAndreas Jaekel 		return (EXIT_FAILURE);
1377b690436dSAndreas Jaekel 	}
1378b690436dSAndreas Jaekel 
1379b690436dSAndreas Jaekel 	snprintf(buf, sizeof(buf),
1380b690436dSAndreas Jaekel 		 "/devices/pseudo/zev@0:%s", aq.zev_name);
1381b690436dSAndreas Jaekel 	q_fd = open(buf, O_RDONLY);
1382b690436dSAndreas Jaekel 	if (q_fd < 0) {
1383b690436dSAndreas Jaekel 		perror("opening queue device failed");
1384b690436dSAndreas Jaekel 		return (EXIT_FAILURE);
1385b690436dSAndreas Jaekel 	}
1386b690436dSAndreas Jaekel 
1387b690436dSAndreas Jaekel 	pfd[0].fd = q_fd;
1388b690436dSAndreas Jaekel 	pfd[0].events = POLLIN;
1389b690436dSAndreas Jaekel 
1390b690436dSAndreas Jaekel 	/* drain queue */
139119695134SAndreas Jaekel 	while ((ret = poll(pfd, 1, 0)) > 0) {
1392b690436dSAndreas Jaekel 		if (read(q_fd, buf, sizeof(buf)) < 0) {
1393b690436dSAndreas Jaekel 			perror("read failed");
1394b690436dSAndreas Jaekel 			close(q_fd);
1395b690436dSAndreas Jaekel 			return(EXIT_FAILURE);
1396b690436dSAndreas Jaekel 		}
1397b690436dSAndreas Jaekel 	}
1398b690436dSAndreas Jaekel 	if (ret < 0) {
1399b690436dSAndreas Jaekel 		perror("poll failed");
1400b690436dSAndreas Jaekel 		close(q_fd);
1401b690436dSAndreas Jaekel 		return(EXIT_FAILURE);
1402b690436dSAndreas Jaekel 	}
1403b690436dSAndreas Jaekel 
1404f432e238SAndreas Jaekel 	fprintf(out, "timestamp   events tevents  guids tguids");
1405b690436dSAndreas Jaekel 	if (verbose) {
1406f432e238SAndreas Jaekel 		fprintf(out, "   error   mark  mount umount zvol_w ");
1407f432e238SAndreas Jaekel 		fprintf(out, "zvol_t  close create  mkdir mxattr ");
1408f432e238SAndreas Jaekel 		fprintf(out, "remove  rmdir   link symlnk rename  ");
1409f432e238SAndreas Jaekel 		fprintf(out, "write  trunc setatt    acl");
1410b690436dSAndreas Jaekel 	}
1411f432e238SAndreas Jaekel 	fprintf(out, "\n");
1412b690436dSAndreas Jaekel 	while (cnt) {
1413b690436dSAndreas Jaekel 		t_until = gethrtime() + (interval * 1000000);
1414b690436dSAndreas Jaekel 		ms = interval;
1415b690436dSAndreas Jaekel 		do {
1416b690436dSAndreas Jaekel 			ret = poll(pfd, 1, ms);
1417b690436dSAndreas Jaekel 			t_now = gethrtime();
1418b690436dSAndreas Jaekel 			if (t_now < t_until) {
1419b690436dSAndreas Jaekel 				ms = t_until - t_now;
1420b690436dSAndreas Jaekel 				ms /= 1000000ull;
1421b690436dSAndreas Jaekel 			}
1422b690436dSAndreas Jaekel 			if (ret < 0) {
1423b690436dSAndreas Jaekel 				perror("poll failed");
1424b690436dSAndreas Jaekel 				close(q_fd);
1425b690436dSAndreas Jaekel 				return(EXIT_FAILURE);
1426b690436dSAndreas Jaekel 			}
1427b690436dSAndreas Jaekel 			if (!(pfd[0].revents & POLLIN))
1428b690436dSAndreas Jaekel 				continue;
1429b690436dSAndreas Jaekel 			/* data available */
1430b690436dSAndreas Jaekel 			ret = read(q_fd, buf, sizeof(buf));
1431b690436dSAndreas Jaekel 			if (ret < 0) {
1432b690436dSAndreas Jaekel 				perror("read failed");
1433b690436dSAndreas Jaekel 				close(q_fd);
1434b690436dSAndreas Jaekel 				return(EXIT_FAILURE);
1435b690436dSAndreas Jaekel 			}
1436b690436dSAndreas Jaekel 			if (ret == 0)
1437b690436dSAndreas Jaekel 				continue;
1438b690436dSAndreas Jaekel 			while (ret > off) {
1439b690436dSAndreas Jaekel 				ev = (zev_event_t *)(buf + off);
1440b690436dSAndreas Jaekel 				zev_eventstat(buf + off, ev->header.record_len);
1441b690436dSAndreas Jaekel 				off += ev->header.record_len;
1442b690436dSAndreas Jaekel 			}
1443b690436dSAndreas Jaekel 			off = 0;
1444b690436dSAndreas Jaekel 		} while ((t_now) < t_until && (ms > 0));
1445f432e238SAndreas Jaekel 		zev_eventstat_interval(out);
1446b690436dSAndreas Jaekel 		if (cnt > 0)
1447b690436dSAndreas Jaekel 			cnt--;
1448b690436dSAndreas Jaekel 	}
1449b690436dSAndreas Jaekel 	close(q_fd);
1450f432e238SAndreas Jaekel 	if (outfile)
1451f432e238SAndreas Jaekel 		fclose(out);
1452b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
1453b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
1454b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_runtime)) {
1455b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_runtime, gt);
1456b690436dSAndreas Jaekel 		free(gt);
1457b690436dSAndreas Jaekel 	}
1458b690436dSAndreas Jaekel 	return EXIT_SUCCESS;
1459b690436dSAndreas Jaekel }
1460b690436dSAndreas Jaekel 
1461f432e238SAndreas Jaekel static int
1462f432e238SAndreas Jaekel zev_report(int fd, char *basename)
1463f432e238SAndreas Jaekel {
1464f432e238SAndreas Jaekel 	char filename[MAXPATHLEN];
1465f432e238SAndreas Jaekel 	char count[10];
1466f432e238SAndreas Jaekel 	time_t now;
1467f432e238SAndreas Jaekel 	time_t midnight;
1468f432e238SAndreas Jaekel 	struct tm tm;
1469f432e238SAndreas Jaekel 	int minutes;
1470f432e238SAndreas Jaekel 	int ret;
1471f432e238SAndreas Jaekel 
1472f432e238SAndreas Jaekel 	verbose++;
1473f432e238SAndreas Jaekel 	while (1) {
1474f432e238SAndreas Jaekel 		now = time(NULL);
1475f432e238SAndreas Jaekel 		localtime_r(&now, &tm);
1476f432e238SAndreas Jaekel 		snprintf(filename, sizeof(filename), "%s.%04d-%02d-%02d",
1477f432e238SAndreas Jaekel 		         basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
1478f432e238SAndreas Jaekel 		tm.tm_sec = 0;
1479f432e238SAndreas Jaekel 		tm.tm_min = 0;
1480f432e238SAndreas Jaekel 		tm.tm_hour = 0;
1481f432e238SAndreas Jaekel 		tm.tm_mday++;  /* works for Jan 32nd, Feb 30th, etc. */
1482f432e238SAndreas Jaekel 		midnight = mktime(&tm);
1483f432e238SAndreas Jaekel 		if (now % 60)
1484f432e238SAndreas Jaekel 			sleep(60 - (now % 60));
1485f432e238SAndreas Jaekel 		minutes = (midnight - time(NULL)) / 60;
1486f432e238SAndreas Jaekel 		snprintf(count, sizeof(count), "%d", minutes);
1487f432e238SAndreas Jaekel 		ret = zev_zevstat(fd, "60", count, filename);
1488f432e238SAndreas Jaekel 		if (ret)
1489f432e238SAndreas Jaekel 			return EXIT_FAILURE;
1490f432e238SAndreas Jaekel 	}
1491f432e238SAndreas Jaekel 	return EXIT_SUCCESS; /* never reached */
1492f432e238SAndreas Jaekel }
1493f432e238SAndreas Jaekel 
1494a18c35b9SAndreas Jaekel int
1495a18c35b9SAndreas Jaekel main(int argc, char **argv)
1496a18c35b9SAndreas Jaekel {
1497a18c35b9SAndreas Jaekel 	int fd;
1498a18c35b9SAndreas Jaekel 	int c;
1499a18c35b9SAndreas Jaekel 	extern char *optarg;
15006a6a51eeSAndreas Jaekel 	int create_tmp_queue = 1;
15016a6a51eeSAndreas Jaekel 	char buf[MAXPATHLEN];
1502a5090b97SAndreas Jaekel 	int mode = 0;
1503a5090b97SAndreas Jaekel 	char *arg = NULL;
1504a5090b97SAndreas Jaekel 	char *arg2 = NULL;
1505b690436dSAndreas Jaekel 	char *p;
1506b690436dSAndreas Jaekel 
150750da9edeSAndreas Jaekel 	/* open device */
150850da9edeSAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
150950da9edeSAndreas Jaekel 	if (fd < 0) {
151050da9edeSAndreas Jaekel 		perror("opening zev device failed");
151150da9edeSAndreas Jaekel 		return EXIT_FAILURE;
151250da9edeSAndreas Jaekel 	}
151350da9edeSAndreas Jaekel 
1514b690436dSAndreas Jaekel 	p = strrchr(argv[0], '/');
1515b690436dSAndreas Jaekel 	if (!p) {
1516b690436dSAndreas Jaekel 		p = argv[0];
1517b690436dSAndreas Jaekel 	} else {
1518b690436dSAndreas Jaekel 		p++;
1519b690436dSAndreas Jaekel 	}
1520b690436dSAndreas Jaekel 	if (!strcmp(p, "zevstat")) {
1521b690436dSAndreas Jaekel 		mode = MD_ZEVSTAT;
152250da9edeSAndreas Jaekel 		if (argc < 2)
152350da9edeSAndreas Jaekel 			zevstat_usage(argv[0]);
152450da9edeSAndreas Jaekel 		if (!strcmp(argv[1], "-v")) {
152550da9edeSAndreas Jaekel 			if (argc < 3)
152650da9edeSAndreas Jaekel 				zevstat_usage(argv[0]);
152750da9edeSAndreas Jaekel 			verbose++;
152850da9edeSAndreas Jaekel 			arg = argv[2];
152950da9edeSAndreas Jaekel 			arg2 = argv[3];
153050da9edeSAndreas Jaekel 		} else {
153150da9edeSAndreas Jaekel 			arg = argv[1];
153250da9edeSAndreas Jaekel 			arg2 = argv[2];
153350da9edeSAndreas Jaekel 		}
1534f432e238SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
1535f432e238SAndreas Jaekel 	} else if(!strcmp(p, "zevreport")) {
1536f432e238SAndreas Jaekel 		mode = MD_ZEV_REPORT;
1537f432e238SAndreas Jaekel 		if (argc != 2)
1538f432e238SAndreas Jaekel 			zevreport_usage(argv[0]);
1539f432e238SAndreas Jaekel 		return zev_report(fd, argv[1]);
1540b690436dSAndreas Jaekel 	}
1541a18c35b9SAndreas Jaekel 
15426a6a51eeSAndreas Jaekel 	while ((c = getopt(argc, argv,
1543174dc952SAndreas Jaekel 	                   "gvspc:d:Dlk:L:q:Q:t:m:M:a:A:r:P:b:B:T:R:h?")) != -1){
1544a18c35b9SAndreas Jaekel 		switch(c) {
154516ff6b2fSAndreas Jaekel 		case 'g':
154616ff6b2fSAndreas Jaekel 			grep_friendly++;
154716ff6b2fSAndreas Jaekel 			verbose++;
154816ff6b2fSAndreas Jaekel 			break;
1549205ed6bfSAndreas Jaekel 		case 'v':
1550205ed6bfSAndreas Jaekel 			verbose++;
1551205ed6bfSAndreas Jaekel 			break;
1552a18c35b9SAndreas Jaekel 		case 's':
1553a5090b97SAndreas Jaekel 			mode = MD_STATISTICS;
1554a5090b97SAndreas Jaekel 			break;
1555a18c35b9SAndreas Jaekel 		case 'p':
1556a5090b97SAndreas Jaekel 			mode = MD_POLL_EVENTS;
1557a5090b97SAndreas Jaekel 			break;
155842110aacSAndreas Jaekel 		case 'c':
1559a5090b97SAndreas Jaekel 			mode = MD_CHECKSUMS;
1560a5090b97SAndreas Jaekel 			arg = optarg;
1561a5090b97SAndreas Jaekel 			break;
1562add9520fSAndreas Jaekel 		case 'D':
1563a5090b97SAndreas Jaekel 			mode = MD_DEBUG_INFO;
1564a5090b97SAndreas Jaekel 			break;
1565a18c35b9SAndreas Jaekel 		case 'd':
1566add9520fSAndreas Jaekel 			close(fd);
1567a18c35b9SAndreas Jaekel 			zev_device = optarg;
1568add9520fSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1569add9520fSAndreas Jaekel 			if (fd < 0) {
1570add9520fSAndreas Jaekel 				perror("opening zev device failed");
1571add9520fSAndreas Jaekel 				return EXIT_FAILURE;
1572add9520fSAndreas Jaekel 			}
15736a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
15746a6a51eeSAndreas Jaekel 			break;
15756a6a51eeSAndreas Jaekel 		case 'q':
15766a6a51eeSAndreas Jaekel 			snprintf(buf, sizeof(buf),
15776a6a51eeSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
15786a6a51eeSAndreas Jaekel 			close(fd);
15796a6a51eeSAndreas Jaekel 			zev_device = buf;
15806a6a51eeSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
15816a6a51eeSAndreas Jaekel 			if (fd < 0) {
15826a6a51eeSAndreas Jaekel 				perror("opening zev device failed");
15836a6a51eeSAndreas Jaekel 				return EXIT_FAILURE;
15846a6a51eeSAndreas Jaekel 			}
15856a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
1586a18c35b9SAndreas Jaekel 			break;
1587add9520fSAndreas Jaekel 		case 'l':
1588a5090b97SAndreas Jaekel 			mode = MD_LIST_QUEUES;
1589a5090b97SAndreas Jaekel 			break;
1590add9520fSAndreas Jaekel 		case 'Q':
1591a5090b97SAndreas Jaekel 			mode = MD_SET_GLOBAL_MAX_QUEUE_LEN;
1592a5090b97SAndreas Jaekel 			arg = optarg;
1593a5090b97SAndreas Jaekel 			break;
15946a6a51eeSAndreas Jaekel 		case 'L':
1595a5090b97SAndreas Jaekel 			mode = MD_SET_MAX_QUEUE_LEN;
1596a5090b97SAndreas Jaekel 			arg = optarg;
1597a5090b97SAndreas Jaekel 			arg2 = argv[optind];
1598a5090b97SAndreas Jaekel 			break;
1599b690436dSAndreas Jaekel 		case 'T':
1600b690436dSAndreas Jaekel 			mode = MD_ZEVSTAT;
1601b690436dSAndreas Jaekel 			arg = optarg;
1602b690436dSAndreas Jaekel 			arg2 = argv[optind];
1603b690436dSAndreas Jaekel 			break;
1604f432e238SAndreas Jaekel 		case 'R':
1605f432e238SAndreas Jaekel 			mode = MD_ZEV_REPORT;
1606f432e238SAndreas Jaekel 			arg = optarg;
1607f432e238SAndreas Jaekel 			break;
1608fec460f8SAndreas Jaekel 		case 't':
1609a5090b97SAndreas Jaekel 			mode = MD_SET_POLL_WAKEUP_QUEUE_LEN;
1610a5090b97SAndreas Jaekel 			arg = optarg;
1611a5090b97SAndreas Jaekel 			arg2 = argv[optind];
1612a5090b97SAndreas Jaekel 			break;
1613a18c35b9SAndreas Jaekel 		case 'm':
1614a5090b97SAndreas Jaekel 			mode = MD_MUTE_POOL;
1615a5090b97SAndreas Jaekel 			arg = optarg;
1616a5090b97SAndreas Jaekel 			break;
1617a18c35b9SAndreas Jaekel 		case 'M':
1618a5090b97SAndreas Jaekel 			mode = MD_UNMUTE_POOL;
1619a5090b97SAndreas Jaekel 			arg = optarg;
1620a5090b97SAndreas Jaekel 			break;
1621888fea18SAndreas Jaekel 		case 'k':
1622a5090b97SAndreas Jaekel 			mode = MD_MARK;
1623a5090b97SAndreas Jaekel 			arg = optarg;
1624a5090b97SAndreas Jaekel 			break;
1625add9520fSAndreas Jaekel 		case 'a':
1626a5090b97SAndreas Jaekel 			mode = MD_ADD_QUEUE;
1627a5090b97SAndreas Jaekel 			arg = optarg;
1628a5090b97SAndreas Jaekel 			break;
16296a6a51eeSAndreas Jaekel 		case 'A':
1630a5090b97SAndreas Jaekel 			mode = MD_ADD_BLOCKING_QUEUE;
1631a5090b97SAndreas Jaekel 			arg = optarg;
1632a5090b97SAndreas Jaekel 			break;
1633add9520fSAndreas Jaekel 		case 'r':
1634a5090b97SAndreas Jaekel 			mode = MD_REMOVE_QUEUE;
1635a5090b97SAndreas Jaekel 			arg = optarg;
1636a5090b97SAndreas Jaekel 			break;
1637add9520fSAndreas Jaekel 		case 'b':
1638a5090b97SAndreas Jaekel 			mode = MD_QUEUE_BLOCKING;
1639a5090b97SAndreas Jaekel 			arg = optarg;
1640a5090b97SAndreas Jaekel 			break;
1641add9520fSAndreas Jaekel 		case 'B':
1642a5090b97SAndreas Jaekel 			mode = MD_QUEUE_NONBLOCKING;
1643a5090b97SAndreas Jaekel 			arg = optarg;
1644a5090b97SAndreas Jaekel 			break;
1645add9520fSAndreas Jaekel 		case 'P':
1646a5090b97SAndreas Jaekel 			mode = MD_QUEUE_PROPERTIES;
1647a5090b97SAndreas Jaekel 			arg = optarg;
1648a5090b97SAndreas Jaekel 			break;
1649a18c35b9SAndreas Jaekel 		case 'h':
1650a18c35b9SAndreas Jaekel 		case '?':
1651a18c35b9SAndreas Jaekel 		default:
1652a18c35b9SAndreas Jaekel 			usage(argv[0]);
1653a18c35b9SAndreas Jaekel 		}
1654a18c35b9SAndreas Jaekel 	}
1655a5090b97SAndreas Jaekel 
1656a5090b97SAndreas Jaekel 	switch (mode) {
1657a5090b97SAndreas Jaekel 	case MD_STATISTICS:
1658a5090b97SAndreas Jaekel 		return zev_statistics(fd);
1659a5090b97SAndreas Jaekel 	case MD_POLL_EVENTS:
1660a5090b97SAndreas Jaekel 		return zev_poll_events(fd, create_tmp_queue);
1661a5090b97SAndreas Jaekel 	case MD_CHECKSUMS:
1662a5090b97SAndreas Jaekel 		return zev_checksum(fd, arg);
1663a5090b97SAndreas Jaekel 	case MD_DEBUG_INFO:
1664a5090b97SAndreas Jaekel 		return zev_debug_info(fd);
1665a5090b97SAndreas Jaekel 	case MD_LIST_QUEUES:
1666a5090b97SAndreas Jaekel 		return zev_list_queues(fd);
1667a5090b97SAndreas Jaekel 	case MD_SET_GLOBAL_MAX_QUEUE_LEN:
1668a5090b97SAndreas Jaekel 		return zev_set_global_max_queue_len(fd, arg);
1669a5090b97SAndreas Jaekel 	case MD_SET_MAX_QUEUE_LEN:
1670a5090b97SAndreas Jaekel 		return zev_set_max_queue_len(fd, arg, arg2);
1671a5090b97SAndreas Jaekel 	case MD_SET_POLL_WAKEUP_QUEUE_LEN:
1672a5090b97SAndreas Jaekel 		return zev_set_poll_wakeup_queue_len(fd, arg, arg2);
1673b690436dSAndreas Jaekel 	case MD_ZEVSTAT:
1674f432e238SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
1675f432e238SAndreas Jaekel 	case MD_ZEV_REPORT:
1676f432e238SAndreas Jaekel 		return zev_report(fd, arg);
1677a5090b97SAndreas Jaekel 	case MD_MUTE_POOL:
1678a5090b97SAndreas Jaekel 		return zev_mute_pool(fd, arg);
1679a5090b97SAndreas Jaekel 	case MD_UNMUTE_POOL:
1680a5090b97SAndreas Jaekel 		return zev_unmute_pool(fd, arg);
1681a5090b97SAndreas Jaekel 	case MD_MARK:
1682a5090b97SAndreas Jaekel 		return zev_mark(fd, arg);
1683a5090b97SAndreas Jaekel 	case MD_ADD_QUEUE:
1684a5090b97SAndreas Jaekel 		return zev_add_queue(fd, arg, 0);
1685a5090b97SAndreas Jaekel 	case MD_ADD_BLOCKING_QUEUE:
1686a5090b97SAndreas Jaekel 		return zev_add_queue(fd, arg, 1);
1687a5090b97SAndreas Jaekel 	case MD_REMOVE_QUEUE:
1688a5090b97SAndreas Jaekel 		return zev_remove_queue(fd, arg);
1689a5090b97SAndreas Jaekel 	case MD_QUEUE_BLOCKING:
1690a5090b97SAndreas Jaekel 		return zev_queue_blocking(fd, arg, 0);
1691a5090b97SAndreas Jaekel 	case MD_QUEUE_NONBLOCKING:
1692a5090b97SAndreas Jaekel 		return zev_queue_blocking(fd, arg, 1);
1693a5090b97SAndreas Jaekel 	case MD_QUEUE_PROPERTIES:
1694a5090b97SAndreas Jaekel 		return zev_queue_properties(fd, arg);
1695a5090b97SAndreas Jaekel 	default:
1696a18c35b9SAndreas Jaekel 		close(fd);
1697a5090b97SAndreas Jaekel 		usage(argv[0]);
1698add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1699a5090b97SAndreas Jaekel 	};
1700a18c35b9SAndreas Jaekel }
1701a18c35b9SAndreas Jaekel 
1702