xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision a0d677d8097eab828b32cffa88a1330795a696ec)
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);
27494875cb8SAndreas Jaekel 		zev_print_inode_info("covered", &rec->covered);
27516ff6b2fSAndreas Jaekel 		znl();
27616ff6b2fSAndreas Jaekel 	} else {
277f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
278f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
279f2dd45e5SAndreas Jaekel 		       rec->guid);
280f2dd45e5SAndreas Jaekel 	}
28116ff6b2fSAndreas Jaekel }
282f2dd45e5SAndreas Jaekel 
283f2dd45e5SAndreas Jaekel static void
284f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf)
285f2dd45e5SAndreas Jaekel {
286f2dd45e5SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
287f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
288f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
289f2dd45e5SAndreas Jaekel 
29016ff6b2fSAndreas Jaekel 	if (verbose) {
29116ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
29216ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
29312119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
29416ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
29516ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
29616ff6b2fSAndreas Jaekel 		znl();
29716ff6b2fSAndreas Jaekel 	} else {
298f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
299f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
300f2dd45e5SAndreas Jaekel 		       rec->guid,
301f2dd45e5SAndreas Jaekel 		       rec->offset,
302f2dd45e5SAndreas Jaekel 		       rec->length);
303f2dd45e5SAndreas Jaekel 	}
30416ff6b2fSAndreas Jaekel }
305f2dd45e5SAndreas Jaekel 
306f2dd45e5SAndreas Jaekel static void
307f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf)
308f2dd45e5SAndreas Jaekel {
309f2dd45e5SAndreas Jaekel 	zev_print_zvol_truncate(buf);
310f2dd45e5SAndreas Jaekel }
311f2dd45e5SAndreas Jaekel 
312f2dd45e5SAndreas Jaekel static void
313f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
314f2dd45e5SAndreas Jaekel {
315f2dd45e5SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
316f2dd45e5SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
317f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
318f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
319f2dd45e5SAndreas Jaekel 
32016ff6b2fSAndreas Jaekel 	if (verbose) {
32116ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
32216ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
32316ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
32416ff6b2fSAndreas Jaekel 		znl();
32516ff6b2fSAndreas Jaekel 	} else {
326f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
327f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
328f2dd45e5SAndreas Jaekel 		       rec->guid,
329f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
330f2dd45e5SAndreas Jaekel 	}
33116ff6b2fSAndreas Jaekel }
332f2dd45e5SAndreas Jaekel 
333f2dd45e5SAndreas Jaekel static void
334f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf)
335f2dd45e5SAndreas Jaekel {
336f2dd45e5SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
337f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
338f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
3392eabeab5SAndreas Jaekel 	zev_sig_t *sig;
3402eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
341f2dd45e5SAndreas Jaekel 
34216ff6b2fSAndreas Jaekel 	if (verbose) {
34316ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
34416ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
34512119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
34616ff6b2fSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
3472eabeab5SAndreas Jaekel 		sig = &rec->signature;
3482eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
3492eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
3502eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
35116ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
35212119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
35316ff6b2fSAndreas Jaekel 		znl();
35416ff6b2fSAndreas Jaekel 	} else {
35535d4e8ddSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
35635d4e8ddSAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
357f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
358f2dd45e5SAndreas Jaekel 		       rec->guid,
359f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
360f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
36135d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
362f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
363f2dd45e5SAndreas Jaekel 	}
36416ff6b2fSAndreas Jaekel }
365f2dd45e5SAndreas Jaekel 
366f2dd45e5SAndreas Jaekel static void
367f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf)
368f2dd45e5SAndreas Jaekel {
369f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
370f2dd45e5SAndreas Jaekel }
371f2dd45e5SAndreas Jaekel 
372f2dd45e5SAndreas Jaekel static void
373f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
374f2dd45e5SAndreas Jaekel {
375f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
376f2dd45e5SAndreas Jaekel }
377f2dd45e5SAndreas Jaekel 
378f2dd45e5SAndreas Jaekel static void
379f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf)
380f2dd45e5SAndreas Jaekel {
381f2dd45e5SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
382f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
383f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
384f2dd45e5SAndreas Jaekel 
38516ff6b2fSAndreas Jaekel 	if (verbose) {
38616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
38716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
38812119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
38916ff6b2fSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
39016ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
39112119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
39216ff6b2fSAndreas Jaekel 		znl();
39316ff6b2fSAndreas Jaekel 	} else {
39416ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
39516ff6b2fSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
396f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
397f2dd45e5SAndreas Jaekel 		       rec->guid,
398f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
39997dcf88dSAndreas Jaekel 		       rec->file.mtime,
400f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
401f2dd45e5SAndreas Jaekel 	}
40216ff6b2fSAndreas Jaekel }
403f2dd45e5SAndreas Jaekel 
404f2dd45e5SAndreas Jaekel static void
405f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf)
406f2dd45e5SAndreas Jaekel {
407f2dd45e5SAndreas Jaekel 	zev_print_znode_remove(buf);
408f2dd45e5SAndreas Jaekel }
409f2dd45e5SAndreas Jaekel 
410f2dd45e5SAndreas Jaekel static void
411f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf)
412f2dd45e5SAndreas Jaekel {
413f2dd45e5SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
414f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
415f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
416f2dd45e5SAndreas Jaekel 
41716ff6b2fSAndreas Jaekel 	if (verbose) {
41816ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
41916ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
42012119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
42116ff6b2fSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
42216ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
42312119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
42416ff6b2fSAndreas Jaekel 		znl();
42516ff6b2fSAndreas Jaekel 	} else {
426a01b300aSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
427a01b300aSAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
428f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
429f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
430f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
431a01b300aSAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
432f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
43316ff6b2fSAndreas Jaekel 	}
434f2dd45e5SAndreas Jaekel }
435f2dd45e5SAndreas Jaekel 
436f2dd45e5SAndreas Jaekel static void
437f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf)
438f2dd45e5SAndreas Jaekel {
439f2dd45e5SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
440f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
441f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
4422eabeab5SAndreas Jaekel 	zev_sig_t *sig;
4432eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
444f2dd45e5SAndreas Jaekel 
44516ff6b2fSAndreas Jaekel 	if (verbose) {
44616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
44716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
44812119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
44916ff6b2fSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
45016ff6b2fSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
4512eabeab5SAndreas Jaekel 		sig = &rec->signature;
4522eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
4532eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
4542eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
45516ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
45612119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
45716ff6b2fSAndreas Jaekel 		znl();
45816ff6b2fSAndreas Jaekel 	} else {
45916ff6b2fSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
46016ff6b2fSAndreas Jaekel 		       "name='%s' link='%s'\n",
461f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
462f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
463f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
464f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec),
465f2dd45e5SAndreas Jaekel 		       ZEV_LINK(rec));
466f2dd45e5SAndreas Jaekel 	}
46716ff6b2fSAndreas Jaekel }
468f2dd45e5SAndreas Jaekel 
469f2dd45e5SAndreas Jaekel static void
470f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf)
471f2dd45e5SAndreas Jaekel {
472f2dd45e5SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
473f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
474f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
475f2dd45e5SAndreas Jaekel 
47616ff6b2fSAndreas Jaekel 	if (verbose) {
47716ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
47816ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
47912119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
48016ff6b2fSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
48116ff6b2fSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
48216ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
48316ff6b2fSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
48416ff6b2fSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
48516ff6b2fSAndreas Jaekel 		znl();
48616ff6b2fSAndreas Jaekel 	} else {
48716ff6b2fSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
48816ff6b2fSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
48916ff6b2fSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
49016ff6b2fSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
491f2dd45e5SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
492f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
493f2dd45e5SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
494f2dd45e5SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
495f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
49635d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
49735d4e8ddSAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
49835d4e8ddSAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
499f2dd45e5SAndreas Jaekel 		       ZEV_SRCNAME(rec),
500f2dd45e5SAndreas Jaekel 		       ZEV_DSTNAME(rec));
501f2dd45e5SAndreas Jaekel 	}
50216ff6b2fSAndreas Jaekel }
503f2dd45e5SAndreas Jaekel 
504f2dd45e5SAndreas Jaekel static void
505f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf)
506f2dd45e5SAndreas Jaekel {
507f2dd45e5SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
508f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
509f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
510205ed6bfSAndreas Jaekel 	zev_sig_t *sig;
511205ed6bfSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
512205ed6bfSAndreas Jaekel 	int i;
513f2dd45e5SAndreas Jaekel 
514205ed6bfSAndreas Jaekel 	if (verbose) {
51516ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
51616ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
51712119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
51816ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
51916ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
52016ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
52116ff6b2fSAndreas Jaekel 		znl();
522205ed6bfSAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
523205ed6bfSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
524205ed6bfSAndreas Jaekel 			sig += i;
525205ed6bfSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
5262eabeab5SAndreas Jaekel 			zpf("  sig: level %d, offset %llu, value %s",
527205ed6bfSAndreas Jaekel 			    sig->level, sig->block_offset, sigval);
528205ed6bfSAndreas Jaekel 		}
52916ff6b2fSAndreas Jaekel 	} else {
53016ff6b2fSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
53116ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
53216ff6b2fSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
53316ff6b2fSAndreas Jaekel 		       rec->offset, rec->length);
534205ed6bfSAndreas Jaekel 	}
535f2dd45e5SAndreas Jaekel }
536f2dd45e5SAndreas Jaekel 
537f2dd45e5SAndreas Jaekel static void
538f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf)
539f2dd45e5SAndreas Jaekel {
540f2dd45e5SAndreas Jaekel 	zev_print_znode_write(buf);
541f2dd45e5SAndreas Jaekel }
542f2dd45e5SAndreas Jaekel 
543f2dd45e5SAndreas Jaekel static void
544f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf)
545f2dd45e5SAndreas Jaekel {
546f2dd45e5SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
547f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
548f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
549f2dd45e5SAndreas Jaekel 
55016ff6b2fSAndreas Jaekel 	if (verbose) {
55116ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
55216ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
55312119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
55416ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
55516ff6b2fSAndreas Jaekel 		znl();
55616ff6b2fSAndreas Jaekel 	} else {
55735d4e8ddSAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
558f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
55935d4e8ddSAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
560f2dd45e5SAndreas Jaekel 	}
56116ff6b2fSAndreas Jaekel }
562f2dd45e5SAndreas Jaekel 
563f2dd45e5SAndreas Jaekel static void
564f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf)
565f2dd45e5SAndreas Jaekel {
566f2dd45e5SAndreas Jaekel 	zev_print_znode_setattr(buf);
567f2dd45e5SAndreas Jaekel }
568f2dd45e5SAndreas Jaekel 
569f2dd45e5SAndreas Jaekel static void
570aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
571aafc540fSAndreas Jaekel {
572f2dd45e5SAndreas Jaekel 	int record_len;
573f2dd45e5SAndreas Jaekel 	int op;
574aafc540fSAndreas Jaekel 
575f2dd45e5SAndreas Jaekel 	record_len = *(uint32_t *)buf;
576f2dd45e5SAndreas Jaekel 	if (record_len != len) {
577f2dd45e5SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
578f2dd45e5SAndreas Jaekel 		        record_len, len);
579aafc540fSAndreas Jaekel 		exit(1);
580aafc540fSAndreas Jaekel 	}
581f2dd45e5SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
582aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
583f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
584aafc540fSAndreas Jaekel 		exit(1);
585aafc540fSAndreas Jaekel 	}
586f2dd45e5SAndreas Jaekel 	switch (op) {
587f2dd45e5SAndreas Jaekel 	case ZEV_OP_ERROR:
588f2dd45e5SAndreas Jaekel 		zev_print_error(buf);
589aafc540fSAndreas Jaekel 		break;
590888fea18SAndreas Jaekel 	case ZEV_OP_MARK:
591888fea18SAndreas Jaekel 		zev_print_mark(buf);
592888fea18SAndreas Jaekel 		break;
593f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
594f2dd45e5SAndreas Jaekel 		zev_print_zfs_mount(buf);
595aafc540fSAndreas Jaekel 		break;
596f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
597f2dd45e5SAndreas Jaekel 		zev_print_zfs_umount(buf);
598aafc540fSAndreas Jaekel 		break;
599f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
600f2dd45e5SAndreas Jaekel 		zev_print_zvol_truncate(buf);
601aafc540fSAndreas Jaekel 		break;
602f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
603f2dd45e5SAndreas Jaekel 		zev_print_zvol_write(buf);
604f2dd45e5SAndreas Jaekel 		break;
605f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
606f2dd45e5SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
607f2dd45e5SAndreas Jaekel 		break;
608f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
609f2dd45e5SAndreas Jaekel 		zev_print_znode_create(buf);
610f2dd45e5SAndreas Jaekel 		break;
611f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
612f2dd45e5SAndreas Jaekel 		zev_print_znode_mkdir(buf);
613f2dd45e5SAndreas Jaekel 		break;
614f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
615f2dd45e5SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
616f2dd45e5SAndreas Jaekel 		break;
617f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
618f2dd45e5SAndreas Jaekel 		zev_print_znode_remove(buf);
619f2dd45e5SAndreas Jaekel 		break;
620f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
621f2dd45e5SAndreas Jaekel 		zev_print_znode_rmdir(buf);
622f2dd45e5SAndreas Jaekel 		break;
623f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
624f2dd45e5SAndreas Jaekel 		zev_print_znode_link(buf);
625f2dd45e5SAndreas Jaekel 		break;
626f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
627f2dd45e5SAndreas Jaekel 		zev_print_znode_symlink(buf);
628f2dd45e5SAndreas Jaekel 		break;
629f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
630f2dd45e5SAndreas Jaekel 		zev_print_znode_rename(buf);
631f2dd45e5SAndreas Jaekel 		break;
632f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
633f2dd45e5SAndreas Jaekel 		zev_print_znode_write(buf);
634f2dd45e5SAndreas Jaekel 		break;
635f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
636f2dd45e5SAndreas Jaekel 		zev_print_znode_truncate(buf);
637f2dd45e5SAndreas Jaekel 		break;
638f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
639f2dd45e5SAndreas Jaekel 		zev_print_znode_setattr(buf);
640f2dd45e5SAndreas Jaekel 		break;
641f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
642f2dd45e5SAndreas Jaekel 		zev_print_znode_acl(buf);
643aafc540fSAndreas Jaekel 		break;
644aafc540fSAndreas Jaekel 	default:
645f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
646aafc540fSAndreas Jaekel 		exit(1);
647aafc540fSAndreas Jaekel 	}
648aafc540fSAndreas Jaekel }
649aafc540fSAndreas Jaekel 
650add9520fSAndreas Jaekel static int
6516a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
652a18c35b9SAndreas Jaekel {
653a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
654a18c35b9SAndreas Jaekel 	int ret;
655aafc540fSAndreas Jaekel 	char buf[4096];
656d979f56cSAndreas Jaekel 	zev_event_t *ev;
657d979f56cSAndreas Jaekel 	int off = 0;
658add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
659add9520fSAndreas Jaekel 	int q_fd;
660add9520fSAndreas Jaekel 
6616a6a51eeSAndreas Jaekel 	if (create_tmp_queue) {
662add9520fSAndreas Jaekel 		aq.zev_max_queue_len = 0;
663add9520fSAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
664add9520fSAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
665add9520fSAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
666add9520fSAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
667add9520fSAndreas Jaekel 
668add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
669add9520fSAndreas Jaekel 			perror("adding temporary queue failed");
670add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
671add9520fSAndreas Jaekel 		}
672add9520fSAndreas Jaekel 
6736a6a51eeSAndreas Jaekel 		snprintf(buf, sizeof(buf),
6746a6a51eeSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
675add9520fSAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
676add9520fSAndreas Jaekel 		if (q_fd < 0) {
677add9520fSAndreas Jaekel 			perror("opening queue device failed");
678add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
679add9520fSAndreas Jaekel 		}
6806a6a51eeSAndreas Jaekel 	} else {
6816a6a51eeSAndreas Jaekel 		q_fd = fd;
6826a6a51eeSAndreas Jaekel 	}
683add9520fSAndreas Jaekel 
684a18c35b9SAndreas Jaekel 	while (1) {
685add9520fSAndreas Jaekel 		pfd[0].fd = q_fd;
686a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
687a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
688a18c35b9SAndreas Jaekel 		if (ret < 0) {
689a18c35b9SAndreas Jaekel 			perror("poll failed");
6906a6a51eeSAndreas Jaekel 			close(q_fd);
691add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
692a18c35b9SAndreas Jaekel 		}
693a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
694a18c35b9SAndreas Jaekel 			continue;
695a18c35b9SAndreas Jaekel 		/* data available */
696add9520fSAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
697a18c35b9SAndreas Jaekel 		if (ret < 0) {
698a18c35b9SAndreas Jaekel 			perror("read failed");
6996a6a51eeSAndreas Jaekel 			close(q_fd);
700add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
701a18c35b9SAndreas Jaekel 		}
702a18c35b9SAndreas Jaekel 		if (ret == 0)
703a18c35b9SAndreas Jaekel 			continue;
704d979f56cSAndreas Jaekel 		while (ret > off) {
705d979f56cSAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
706d979f56cSAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
707d979f56cSAndreas Jaekel 			off += ev->header.record_len;
708d979f56cSAndreas Jaekel 		}
709149d0affSAndreas Jaekel 		off = 0;
710a18c35b9SAndreas Jaekel 	}
7116a6a51eeSAndreas Jaekel 	if (create_tmp_queue)
712add9520fSAndreas Jaekel 		close(q_fd);
713add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
714a18c35b9SAndreas Jaekel }
715a18c35b9SAndreas Jaekel 
716a18c35b9SAndreas Jaekel static void
717a18c35b9SAndreas Jaekel usage(char *progname)
718a18c35b9SAndreas Jaekel {
719add9520fSAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
720add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
721add9520fSAndreas Jaekel 	fprintf(stderr, " Status information:\n");
722a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
723a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
724add9520fSAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
725add9520fSAndreas Jaekel 	        "information\n");
726b690436dSAndreas Jaekel 	fprintf(stderr, "   -T <interval> <cnt>  zevstat mode\n");
727f432e238SAndreas Jaekel 	fprintf(stderr, "   -R <base filename>   zevreport mode\n");
728add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
729add9520fSAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
730add9520fSAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
731add9520fSAndreas Jaekel 	        "length\n");
732add9520fSAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
733add9520fSAndreas Jaekel 	        "this pool\n");
734a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
735add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
736add9520fSAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
737add9520fSAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
7386a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
7396a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
740add9520fSAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
741add9520fSAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
742add9520fSAndreas Jaekel 	        "(default)\n");
743add9520fSAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
744add9520fSAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
7456a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
746add9520fSAndreas Jaekel 	        "length\n");
747add9520fSAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
748add9520fSAndreas Jaekel 	        "throttle\n");
749add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
750add9520fSAndreas Jaekel 	fprintf(stderr, " Other options:\n");
751add9520fSAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
752add9520fSAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
7536a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
7546a6a51eeSAndreas Jaekel 		"queue name\n");
755888fea18SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
75642110aacSAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
75742110aacSAndreas Jaekel 		"checksums\n");
75816ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
759205ed6bfSAndreas Jaekel 	        "for some operations\n");
76016ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
76116ff6b2fSAndreas Jaekel 	        "one event per line\n");
762a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
763a18c35b9SAndreas Jaekel }
764a18c35b9SAndreas Jaekel 
76550da9edeSAndreas Jaekel static void
76650da9edeSAndreas Jaekel zevstat_usage(char *progname)
76750da9edeSAndreas Jaekel {
76850da9edeSAndreas Jaekel 	fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname);
76950da9edeSAndreas Jaekel 	fprintf(stderr, "   -v   verbose, show counters for all event types\n");
77050da9edeSAndreas Jaekel 	exit (EXIT_FAILURE);
77150da9edeSAndreas Jaekel }
77250da9edeSAndreas Jaekel 
773f432e238SAndreas Jaekel static void
774f432e238SAndreas Jaekel zevreport_usage(char *progname)
775f432e238SAndreas Jaekel {
776f432e238SAndreas Jaekel 	fprintf(stderr, "usage: %s <output base filename>\n", progname);
777f432e238SAndreas Jaekel 	exit (EXIT_FAILURE);
778f432e238SAndreas Jaekel }
779f432e238SAndreas Jaekel 
780a18c35b9SAndreas Jaekel static int
7816a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
782a18c35b9SAndreas Jaekel {
783add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
784add9520fSAndreas Jaekel 	int namelen;
785a18c35b9SAndreas Jaekel 
786add9520fSAndreas Jaekel 	namelen = strlen(arg);
787add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
788add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
789a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
790a18c35b9SAndreas Jaekel 	}
791add9520fSAndreas Jaekel 
792add9520fSAndreas Jaekel 	aq.zev_namelen = namelen;
793add9520fSAndreas Jaekel 	strcpy(aq.zev_name, arg);
794c99a1a25SAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT | ZEV_FL_INITIALLY_EMPTY;
7956a6a51eeSAndreas Jaekel 	if (blocking) {
7966a6a51eeSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
7976a6a51eeSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
7986a6a51eeSAndreas Jaekel 	} else {
799add9520fSAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
8006a6a51eeSAndreas Jaekel 	}
801add9520fSAndreas Jaekel 
802add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
803add9520fSAndreas Jaekel 		perror("adding queue failed");
804a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
805a18c35b9SAndreas Jaekel 	}
806a18c35b9SAndreas Jaekel 	return (0);
807a18c35b9SAndreas Jaekel }
808a18c35b9SAndreas Jaekel 
809a18c35b9SAndreas Jaekel static int
810add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg)
811fec460f8SAndreas Jaekel {
812add9520fSAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
813add9520fSAndreas Jaekel 	int namelen;
814fec460f8SAndreas Jaekel 
815add9520fSAndreas Jaekel 	namelen = strlen(arg);
816add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
817add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
818fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
819fec460f8SAndreas Jaekel 	}
820add9520fSAndreas Jaekel 
8216a6a51eeSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
8226a6a51eeSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
823add9520fSAndreas Jaekel 
824add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
825add9520fSAndreas Jaekel 		perror("removing queue failed");
826add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
827add9520fSAndreas Jaekel 	}
828add9520fSAndreas Jaekel 	return (0);
829add9520fSAndreas Jaekel }
830add9520fSAndreas Jaekel 
831add9520fSAndreas Jaekel static int
832add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
833add9520fSAndreas Jaekel {
834add9520fSAndreas Jaekel 	uint64_t maxqueuelen;
835add9520fSAndreas Jaekel 
836174dc952SAndreas Jaekel 	if (!arg) {
837174dc952SAndreas Jaekel 		fprintf(stderr, "missing queue length parameter\n");
838174dc952SAndreas Jaekel 		return (EXIT_FAILURE);
839174dc952SAndreas Jaekel 	}
840174dc952SAndreas Jaekel 
841add9520fSAndreas Jaekel 	errno = 0;
842add9520fSAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
843add9520fSAndreas Jaekel 	if (errno) {
844add9520fSAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
845add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
846add9520fSAndreas Jaekel 	}
847add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
848add9520fSAndreas Jaekel 		perror("setting max queue length failed");
849fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
850fec460f8SAndreas Jaekel 	}
851fec460f8SAndreas Jaekel 	return (0);
852fec460f8SAndreas Jaekel }
853fec460f8SAndreas Jaekel 
854fec460f8SAndreas Jaekel static int
855a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
856a18c35b9SAndreas Jaekel {
857a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
858a18c35b9SAndreas Jaekel 	int len;
859a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
860a18c35b9SAndreas Jaekel 	len = strlen(poolname);
861a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
862a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
863a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
864a18c35b9SAndreas Jaekel 	}
865a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
866a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
867a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
868a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
869a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
870a18c35b9SAndreas Jaekel 	}
871a18c35b9SAndreas Jaekel 	return (0);
872a18c35b9SAndreas Jaekel }
873a18c35b9SAndreas Jaekel 
874a18c35b9SAndreas Jaekel int
875a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
876a18c35b9SAndreas Jaekel {
877a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
878a18c35b9SAndreas Jaekel }
879a18c35b9SAndreas Jaekel 
880a18c35b9SAndreas Jaekel int
881a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
882a18c35b9SAndreas Jaekel {
883a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
884a18c35b9SAndreas Jaekel }
885a18c35b9SAndreas Jaekel 
886888fea18SAndreas Jaekel static int
887add9520fSAndreas Jaekel zev_debug_info(int fd)
888add9520fSAndreas Jaekel {
889add9520fSAndreas Jaekel 	zev_ioctl_debug_info_t di;
890add9520fSAndreas Jaekel 
891add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
892add9520fSAndreas Jaekel 		perror("getting zev debug info failed");
893add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
894add9520fSAndreas Jaekel 	}
895add9520fSAndreas Jaekel 
896add9520fSAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
897205ed6bfSAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
898205ed6bfSAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
899205ed6bfSAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
900add9520fSAndreas Jaekel 	return 0;
901add9520fSAndreas Jaekel }
902add9520fSAndreas Jaekel 
903add9520fSAndreas Jaekel static int
904888fea18SAndreas Jaekel zev_mark(int fd, char *arg)
905888fea18SAndreas Jaekel {
906888fea18SAndreas Jaekel 	zev_ioctl_mark_t *mark;
907888fea18SAndreas Jaekel 	uint64_t guid;
908888fea18SAndreas Jaekel 	int len;
909888fea18SAndreas Jaekel 	char *p;
910888fea18SAndreas Jaekel 
911888fea18SAndreas Jaekel 	p = strchr(arg, ':');
912888fea18SAndreas Jaekel 	if (!p) {
913888fea18SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
914888fea18SAndreas Jaekel 		        "e.g. '123:hello'\n");
915888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
916888fea18SAndreas Jaekel 	}
917888fea18SAndreas Jaekel 	*p = '\n';
918888fea18SAndreas Jaekel 	p++;
919888fea18SAndreas Jaekel 
920888fea18SAndreas Jaekel 	errno = 0;
921add9520fSAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
922888fea18SAndreas Jaekel 	if (errno) {
923888fea18SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
924888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
925888fea18SAndreas Jaekel 	}
926888fea18SAndreas Jaekel 
927888fea18SAndreas Jaekel 	len = strlen(p);
928888fea18SAndreas Jaekel 
929888fea18SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
930888fea18SAndreas Jaekel 	if (!mark) {
931888fea18SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
932888fea18SAndreas Jaekel 		        strerror(errno));
933888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
934888fea18SAndreas Jaekel 	}
935888fea18SAndreas Jaekel 	mark->zev_guid = guid;
936888fea18SAndreas Jaekel 	mark->zev_mark_id = 0;
937888fea18SAndreas Jaekel 	mark->zev_payload_len = len;
938888fea18SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
939888fea18SAndreas Jaekel 
940888fea18SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
941888fea18SAndreas Jaekel 		perror("queueing mark failed");
942888fea18SAndreas Jaekel 		return (EXIT_FAILURE);
943888fea18SAndreas Jaekel 	}
944888fea18SAndreas Jaekel 
945888fea18SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
946888fea18SAndreas Jaekel 	return (0);
947888fea18SAndreas Jaekel }
948888fea18SAndreas Jaekel 
949add9520fSAndreas Jaekel static int
950add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
951add9520fSAndreas Jaekel {
952add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
953add9520fSAndreas Jaekel 
9546a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9556a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
956add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
957add9520fSAndreas Jaekel 		return EXIT_FAILURE;
958add9520fSAndreas Jaekel 	}
9596a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
960add9520fSAndreas Jaekel 
961add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
962add9520fSAndreas Jaekel 		perror("getting queue properties failed");
963add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
964add9520fSAndreas Jaekel 	}
965add9520fSAndreas Jaekel 	if (block) {
966add9520fSAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
967add9520fSAndreas Jaekel 	} else {
968add9520fSAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
969add9520fSAndreas Jaekel 	}
970add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
971add9520fSAndreas Jaekel 		perror("setting queue properties failed");
972add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
973add9520fSAndreas Jaekel 	}
974add9520fSAndreas Jaekel 	return (0);
975add9520fSAndreas Jaekel }
976add9520fSAndreas Jaekel 
977add9520fSAndreas Jaekel static int
978add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
979add9520fSAndreas Jaekel {
980add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
981add9520fSAndreas Jaekel 
982add9520fSAndreas Jaekel 	if (!len) {
983add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
984add9520fSAndreas Jaekel 		return EXIT_FAILURE;
985add9520fSAndreas Jaekel 	}
986add9520fSAndreas Jaekel 
9876a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9886a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
989add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
990add9520fSAndreas Jaekel 		return EXIT_FAILURE;
991add9520fSAndreas Jaekel 	}
9926a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
993add9520fSAndreas Jaekel 
994add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
995add9520fSAndreas Jaekel 		perror("getting queue properties failed");
996add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
997add9520fSAndreas Jaekel 	}
998add9520fSAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
999add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
1000add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
1001add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1002add9520fSAndreas Jaekel 	}
1003add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
1004add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
1005add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1006add9520fSAndreas Jaekel 	}
1007add9520fSAndreas Jaekel 
1008add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1009add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1010add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1011add9520fSAndreas Jaekel 	}
1012add9520fSAndreas Jaekel 	return (0);
1013add9520fSAndreas Jaekel }
1014add9520fSAndreas Jaekel 
1015add9520fSAndreas Jaekel static int
1016add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
1017add9520fSAndreas Jaekel {
1018add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1019add9520fSAndreas Jaekel 
1020add9520fSAndreas Jaekel 	if (!len) {
1021add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
1022add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1023add9520fSAndreas Jaekel 	}
1024add9520fSAndreas Jaekel 
10256a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10266a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1027add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1028add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1029add9520fSAndreas Jaekel 	}
10306a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1031add9520fSAndreas Jaekel 
1032add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1033add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1034add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1035add9520fSAndreas Jaekel 	}
1036add9520fSAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
1037add9520fSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
1038add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
1039add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1040add9520fSAndreas Jaekel 	}
10416a6a51eeSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
1042add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
1043add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1044add9520fSAndreas Jaekel 	}
1045add9520fSAndreas Jaekel 
1046add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1047add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1048add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1049add9520fSAndreas Jaekel 	}
1050add9520fSAndreas Jaekel 	return (0);
1051add9520fSAndreas Jaekel }
1052add9520fSAndreas Jaekel 
1053add9520fSAndreas Jaekel static int
1054add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg)
1055add9520fSAndreas Jaekel {
1056add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1057add9520fSAndreas Jaekel 
10586a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10596a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1060add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1061add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1062add9520fSAndreas Jaekel 	}
10636a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1064add9520fSAndreas Jaekel 
1065add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1066add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1067add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1068add9520fSAndreas Jaekel 	}
1069add9520fSAndreas Jaekel 
1070add9520fSAndreas Jaekel 	printf("queue        : %s\n", arg);
1071add9520fSAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1072add9520fSAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1073add9520fSAndreas Jaekel 	printf("persistent   : %s\n",
1074add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1075add9520fSAndreas Jaekel 	printf("blocking     : %s\n",
1076add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1077add9520fSAndreas Jaekel 
1078add9520fSAndreas Jaekel 	return (0);
1079add9520fSAndreas Jaekel }
1080add9520fSAndreas Jaekel 
1081add9520fSAndreas Jaekel static int
1082add9520fSAndreas Jaekel zev_list_queues(int fd)
1083add9520fSAndreas Jaekel {
1084add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1085add9520fSAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1086add9520fSAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1087add9520fSAndreas Jaekel 	uint64_t	i;
1088add9520fSAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1089add9520fSAndreas Jaekel 
1090add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1091add9520fSAndreas Jaekel 		perror("getting queue list failed");
1092add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1093add9520fSAndreas Jaekel 	}
1094add9520fSAndreas Jaekel 
1095add9520fSAndreas Jaekel 	printf("Name                                     Size       "
1096add9520fSAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
1097add9520fSAndreas Jaekel 
1098add9520fSAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1099add9520fSAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1100add9520fSAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1101add9520fSAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1102add9520fSAndreas Jaekel 
11036a6a51eeSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
11046a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11056a6a51eeSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
11066a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1107add9520fSAndreas Jaekel 
1108add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1109add9520fSAndreas Jaekel 			if (errno == ENOENT)
1110add9520fSAndreas Jaekel 				continue;
1111add9520fSAndreas Jaekel 			perror("getting queue properties failed");
1112add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1113add9520fSAndreas Jaekel 		}
1114add9520fSAndreas Jaekel 
11156a6a51eeSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
11166a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11176a6a51eeSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
11186a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1119add9520fSAndreas Jaekel 
1120add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1121add9520fSAndreas Jaekel 			if (errno == ENOENT)
1122add9520fSAndreas Jaekel 				continue;
1123add9520fSAndreas Jaekel 			perror("getting statistics data failed");
1124add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1125add9520fSAndreas Jaekel 		}
1126add9520fSAndreas Jaekel 
1127add9520fSAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
1128add9520fSAndreas Jaekel 		       " %-3s %-3s\n",
1129add9520fSAndreas Jaekel 			name,
1130add9520fSAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1131add9520fSAndreas Jaekel 			gqp.zev_max_queue_len,
1132add9520fSAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
1133add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1134add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1135add9520fSAndreas Jaekel 				 "yes" : "no");
1136add9520fSAndreas Jaekel 	}
1137add9520fSAndreas Jaekel 
1138add9520fSAndreas Jaekel 	return (0);
1139add9520fSAndreas Jaekel }
1140add9520fSAndreas Jaekel 
114142110aacSAndreas Jaekel static int
114242110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename)
114342110aacSAndreas Jaekel {
114442110aacSAndreas Jaekel 	int fd;
114542110aacSAndreas Jaekel 	offset_t off;
114642110aacSAndreas Jaekel 	offset_t data;
114742110aacSAndreas Jaekel 	zev_sig_t *sig;
114842110aacSAndreas Jaekel 	char *buf;
114942110aacSAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
115042110aacSAndreas Jaekel 	int i;
115142110aacSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
115242110aacSAndreas Jaekel 	int buf_size;
115342110aacSAndreas Jaekel 
115442110aacSAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
115542110aacSAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
115642110aacSAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
115742110aacSAndreas Jaekel 	if (!buf) {
115842110aacSAndreas Jaekel 		perror("can't allocate checksum buffer");
115942110aacSAndreas Jaekel 		return (EXIT_FAILURE);
116042110aacSAndreas Jaekel 	}
116142110aacSAndreas Jaekel 
116242110aacSAndreas Jaekel 	fd = open(filename, O_RDONLY);
116342110aacSAndreas Jaekel 	if (fd < 0) {
116442110aacSAndreas Jaekel 		perror("can't open file");
116542110aacSAndreas Jaekel 		return (EXIT_FAILURE);
116642110aacSAndreas Jaekel 	}
116742110aacSAndreas Jaekel 
116842110aacSAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
116942110aacSAndreas Jaekel 	gs->zev_fd = fd;
117042110aacSAndreas Jaekel 	gs->zev_bufsize = buf_size;
117142110aacSAndreas Jaekel 
117242110aacSAndreas Jaekel 	off = 0;
117342110aacSAndreas Jaekel 	data = 0;
117442110aacSAndreas Jaekel 	while (1) {
117542110aacSAndreas Jaekel 		errno = 0;
117642110aacSAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
117742110aacSAndreas Jaekel 		if (data < 0) {
117842110aacSAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
117942110aacSAndreas Jaekel 				break;
118042110aacSAndreas Jaekel 			perror("llseek failed");
118142110aacSAndreas Jaekel 			goto err;
118242110aacSAndreas Jaekel 		}
118342110aacSAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
118442110aacSAndreas Jaekel 		off = data + ZEV_L1_SIZE;
118542110aacSAndreas Jaekel 
118642110aacSAndreas Jaekel 		gs->zev_offset = data;
118742110aacSAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
118842110aacSAndreas Jaekel 
118942110aacSAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
119042110aacSAndreas Jaekel 			perror("ioctl to get signatures failed");
119142110aacSAndreas Jaekel 			goto err;
119242110aacSAndreas Jaekel 		}
119342110aacSAndreas Jaekel 
119442110aacSAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
119542110aacSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
119642110aacSAndreas Jaekel 			sig += i;
119742110aacSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
119842110aacSAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
119942110aacSAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
120042110aacSAndreas Jaekel 		}
120142110aacSAndreas Jaekel 	}
120242110aacSAndreas Jaekel 
120342110aacSAndreas Jaekel 	free(buf);
120442110aacSAndreas Jaekel 	close(fd);
120542110aacSAndreas Jaekel 	return 0;
120642110aacSAndreas Jaekel err:
120742110aacSAndreas Jaekel 	free(buf);
120842110aacSAndreas Jaekel 	close(fd);
120942110aacSAndreas Jaekel 	return (EXIT_FAILURE);
121042110aacSAndreas Jaekel }
121142110aacSAndreas Jaekel 
1212b690436dSAndreas Jaekel typedef struct zevstat {
1213b690436dSAndreas Jaekel 	uint64_t	ns_start;
1214b690436dSAndreas Jaekel 	uint64_t	events[ZEV_OP_MIN + ZEV_OP_MAX];
1215b690436dSAndreas Jaekel 	uint64_t	guids;
1216b690436dSAndreas Jaekel 	uint64_t	total_events;
1217b690436dSAndreas Jaekel 	uint64_t	total_guids;
1218b690436dSAndreas Jaekel 	avl_tree_t	guids_interval;
1219b690436dSAndreas Jaekel 	avl_tree_t	guids_runtime;
1220b690436dSAndreas Jaekel } zevstat_t;
1221b690436dSAndreas Jaekel 
1222b690436dSAndreas Jaekel typedef struct zev_guidtrack_t {
1223b690436dSAndreas Jaekel 	uint64_t	guid;
1224b690436dSAndreas Jaekel 	avl_node_t	avl_interval;
1225b690436dSAndreas Jaekel 	avl_node_t	avl_runtime;
1226b690436dSAndreas Jaekel } zev_guidtrack_t;
1227b690436dSAndreas Jaekel 
1228b690436dSAndreas Jaekel zevstat_t zevstat;
1229b690436dSAndreas Jaekel 
1230b690436dSAndreas Jaekel static void
1231b690436dSAndreas Jaekel zev_eventstat(char *buf, int len)
1232b690436dSAndreas Jaekel {
1233b690436dSAndreas Jaekel 	zev_header_t *rec = (zev_header_t *)buf;
1234b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1235b690436dSAndreas Jaekel 	zev_guidtrack_t *gt_int;
1236b690436dSAndreas Jaekel 	zev_guidtrack_t to_find;
1237b690436dSAndreas Jaekel 	avl_index_t where;
1238b690436dSAndreas Jaekel 
1239b690436dSAndreas Jaekel 	zevstat.total_events++;
1240b690436dSAndreas Jaekel 	zevstat.events[rec->op]++;
1241b690436dSAndreas Jaekel 
1242b690436dSAndreas Jaekel 	to_find.guid = rec->guid;
1243b690436dSAndreas Jaekel 	gt = avl_find(&zevstat.guids_runtime, &to_find, &where);
1244b690436dSAndreas Jaekel 	if (!gt) {
1245b690436dSAndreas Jaekel 		gt = malloc(sizeof(*gt));
1246b690436dSAndreas Jaekel 		if (!gt) {
1247b690436dSAndreas Jaekel 			perror("can't get guid tracking record");
1248b690436dSAndreas Jaekel 			exit (EXIT_FAILURE);
1249b690436dSAndreas Jaekel 		}
1250b690436dSAndreas Jaekel 		gt->guid = rec->guid;
1251b690436dSAndreas Jaekel 		avl_insert(&zevstat.guids_runtime, gt, where);
1252b690436dSAndreas Jaekel 	}
1253b690436dSAndreas Jaekel 	gt_int = avl_find(&zevstat.guids_interval, &to_find, &where);
1254b690436dSAndreas Jaekel 	if (!gt_int)
1255b690436dSAndreas Jaekel 		avl_insert(&zevstat.guids_interval, gt, where);
1256b690436dSAndreas Jaekel }
1257b690436dSAndreas Jaekel 
1258b690436dSAndreas Jaekel static void
1259f432e238SAndreas Jaekel zev_eventstat_interval(FILE *out)
1260b690436dSAndreas Jaekel {
1261b690436dSAndreas Jaekel 	uint64_t events;
1262b690436dSAndreas Jaekel 	int i;
1263b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1264b690436dSAndreas Jaekel 
1265b690436dSAndreas Jaekel 	events = 0;
1266b690436dSAndreas Jaekel 	for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) {
1267b690436dSAndreas Jaekel 		events += zevstat.events[i];
1268b690436dSAndreas Jaekel 	}
1269b690436dSAndreas Jaekel 
1270b690436dSAndreas Jaekel 	if (verbose) {
1271f432e238SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu  ",
1272b690436dSAndreas Jaekel 		        time(NULL),
1273b690436dSAndreas Jaekel 		        events,
1274b690436dSAndreas Jaekel 		        zevstat.total_events,
1275b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
1276b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
1277b690436dSAndreas Jaekel 		for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++)
1278f432e238SAndreas Jaekel 			fprintf(out, "%6llu ", zevstat.events[i]);
1279f432e238SAndreas Jaekel 		fprintf(out, "\n");
1280b690436dSAndreas Jaekel 	} else {
1281f432e238SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu\n",
1282b690436dSAndreas Jaekel 		        time(NULL),
1283b690436dSAndreas Jaekel 		        events,
1284b690436dSAndreas Jaekel 		        zevstat.total_events,
1285b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
1286b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
1287b690436dSAndreas Jaekel 	}
1288b690436dSAndreas Jaekel 	memset(&zevstat.events, 0, sizeof(zevstat.events));
1289b690436dSAndreas Jaekel 	zevstat.guids = 0;
1290b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
1291b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
1292f432e238SAndreas Jaekel 	fflush(out);
1293b690436dSAndreas Jaekel }
1294b690436dSAndreas Jaekel 
1295b690436dSAndreas Jaekel static int
1296b690436dSAndreas Jaekel zev_evcompar(const void *a, const void *b)
1297b690436dSAndreas Jaekel {
1298b690436dSAndreas Jaekel 	const zev_guidtrack_t *ga = a;
1299b690436dSAndreas Jaekel 	const zev_guidtrack_t *gb = b;
1300b690436dSAndreas Jaekel 
1301b690436dSAndreas Jaekel 	if (ga->guid > gb->guid)
1302b690436dSAndreas Jaekel 		return 1;
1303b690436dSAndreas Jaekel 	if (ga->guid < gb->guid)
1304b690436dSAndreas Jaekel 		return -1;
1305b690436dSAndreas Jaekel 	return 0;
1306b690436dSAndreas Jaekel }
1307b690436dSAndreas Jaekel 
1308b690436dSAndreas Jaekel static int
1309f432e238SAndreas Jaekel zev_zevstat(int fd, char *s_interval, char *s_count, char *outfile)
1310b690436dSAndreas Jaekel {
1311b690436dSAndreas Jaekel 	uint64_t interval = 1000;
1312b690436dSAndreas Jaekel 	uint64_t ms;
1313b690436dSAndreas Jaekel 	uint64_t t_until;
1314b690436dSAndreas Jaekel 	uint64_t t_now;
1315b690436dSAndreas Jaekel 	int cnt = -1;
1316b690436dSAndreas Jaekel 	struct pollfd pfd[1];
1317b690436dSAndreas Jaekel 	int ret;
1318b690436dSAndreas Jaekel 	char buf[4096];
1319b690436dSAndreas Jaekel 	zev_event_t *ev;
1320b690436dSAndreas Jaekel 	int off = 0;
1321b690436dSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
1322b690436dSAndreas Jaekel 	int q_fd;
1323b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1324f432e238SAndreas Jaekel 	FILE *out = stdout;
1325f432e238SAndreas Jaekel 	struct stat st;
1326f432e238SAndreas Jaekel 	char filename[MAXPATHLEN];
1327f432e238SAndreas Jaekel 	int retry;
1328f432e238SAndreas Jaekel 
1329f432e238SAndreas Jaekel 	if (outfile) {
1330f432e238SAndreas Jaekel 		retry = 0;
1331f432e238SAndreas Jaekel 		strncpy(filename, outfile, sizeof(filename));
1332f432e238SAndreas Jaekel 		while (stat(filename, &st) == 0) {
1333f432e238SAndreas Jaekel 			/* file exists */
1334f432e238SAndreas Jaekel 			snprintf(filename, sizeof(filename),
1335f432e238SAndreas Jaekel 			         "%s.%d", outfile, retry);
1336f432e238SAndreas Jaekel 			retry++;
1337f432e238SAndreas Jaekel 		}
1338f432e238SAndreas Jaekel 		out = fopen(filename, "wb+");
1339f432e238SAndreas Jaekel 		if (!out) {
1340f432e238SAndreas Jaekel 			perror("opening output file failed");
1341f432e238SAndreas Jaekel 			return (EXIT_FAILURE);
1342f432e238SAndreas Jaekel 		}
1343f432e238SAndreas Jaekel 	}
1344b690436dSAndreas Jaekel 
1345b690436dSAndreas Jaekel 	memset(&zevstat, 0, sizeof(zevstat));
1346b690436dSAndreas Jaekel 	avl_create(&zevstat.guids_runtime, zev_evcompar,
1347b690436dSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
1348b690436dSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_runtime));
1349b690436dSAndreas Jaekel 	avl_create(&zevstat.guids_interval, zev_evcompar,
1350b690436dSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
1351b690436dSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_interval));
1352b690436dSAndreas Jaekel 
135319695134SAndreas Jaekel 	if (s_interval) {
1354b690436dSAndreas Jaekel 		interval = atol(s_interval);
1355b690436dSAndreas Jaekel 		if (interval == 0) {
1356b690436dSAndreas Jaekel 			fprintf(stderr, "invalid interval.\n");
1357b690436dSAndreas Jaekel 			return (EXIT_FAILURE);
1358b690436dSAndreas Jaekel 		}
1359b690436dSAndreas Jaekel 		interval *= 1000;
136019695134SAndreas Jaekel 	}
1361b690436dSAndreas Jaekel 	if (s_count) {
1362b690436dSAndreas Jaekel 		cnt = atol(s_count);
1363b690436dSAndreas Jaekel 		if (interval == 0) {
1364b690436dSAndreas Jaekel 			fprintf(stderr, "invalid count.\n");
1365b690436dSAndreas Jaekel 			return (EXIT_FAILURE);
1366b690436dSAndreas Jaekel 		}
1367b690436dSAndreas Jaekel 	}
1368b690436dSAndreas Jaekel 
1369b690436dSAndreas Jaekel 	aq.zev_max_queue_len = 1024 * 1024;
1370c99a1a25SAndreas Jaekel 	aq.zev_flags = ZEV_FL_INITIALLY_EMPTY;
1371b690436dSAndreas Jaekel 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
1372b690436dSAndreas Jaekel 		 "zevstat.%ld.%ld", time(NULL), getpid());
1373b690436dSAndreas Jaekel 	aq.zev_namelen = strlen(aq.zev_name);
1374b690436dSAndreas Jaekel 
1375b690436dSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
1376b690436dSAndreas Jaekel 		perror("adding temporary queue failed");
1377b690436dSAndreas Jaekel 		return (EXIT_FAILURE);
1378b690436dSAndreas Jaekel 	}
1379b690436dSAndreas Jaekel 
1380b690436dSAndreas Jaekel 	snprintf(buf, sizeof(buf),
1381b690436dSAndreas Jaekel 		 "/devices/pseudo/zev@0:%s", aq.zev_name);
1382b690436dSAndreas Jaekel 	q_fd = open(buf, O_RDONLY);
1383b690436dSAndreas Jaekel 	if (q_fd < 0) {
1384b690436dSAndreas Jaekel 		perror("opening queue device failed");
1385b690436dSAndreas Jaekel 		return (EXIT_FAILURE);
1386b690436dSAndreas Jaekel 	}
1387b690436dSAndreas Jaekel 
1388b690436dSAndreas Jaekel 	pfd[0].fd = q_fd;
1389b690436dSAndreas Jaekel 	pfd[0].events = POLLIN;
1390b690436dSAndreas Jaekel 
1391b690436dSAndreas Jaekel 	/* drain queue */
139219695134SAndreas Jaekel 	while ((ret = poll(pfd, 1, 0)) > 0) {
1393b690436dSAndreas Jaekel 		if (read(q_fd, buf, sizeof(buf)) < 0) {
1394b690436dSAndreas Jaekel 			perror("read failed");
1395b690436dSAndreas Jaekel 			close(q_fd);
1396b690436dSAndreas Jaekel 			return(EXIT_FAILURE);
1397b690436dSAndreas Jaekel 		}
1398b690436dSAndreas Jaekel 	}
1399b690436dSAndreas Jaekel 	if (ret < 0) {
1400b690436dSAndreas Jaekel 		perror("poll failed");
1401b690436dSAndreas Jaekel 		close(q_fd);
1402b690436dSAndreas Jaekel 		return(EXIT_FAILURE);
1403b690436dSAndreas Jaekel 	}
1404b690436dSAndreas Jaekel 
1405f432e238SAndreas Jaekel 	fprintf(out, "timestamp   events tevents  guids tguids");
1406b690436dSAndreas Jaekel 	if (verbose) {
1407f432e238SAndreas Jaekel 		fprintf(out, "   error   mark  mount umount zvol_w ");
1408f432e238SAndreas Jaekel 		fprintf(out, "zvol_t  close create  mkdir mxattr ");
1409f432e238SAndreas Jaekel 		fprintf(out, "remove  rmdir   link symlnk rename  ");
1410f432e238SAndreas Jaekel 		fprintf(out, "write  trunc setatt    acl");
1411b690436dSAndreas Jaekel 	}
1412f432e238SAndreas Jaekel 	fprintf(out, "\n");
1413b690436dSAndreas Jaekel 	while (cnt) {
1414b690436dSAndreas Jaekel 		t_until = gethrtime() + (interval * 1000000);
1415b690436dSAndreas Jaekel 		ms = interval;
1416b690436dSAndreas Jaekel 		do {
1417b690436dSAndreas Jaekel 			ret = poll(pfd, 1, ms);
1418b690436dSAndreas Jaekel 			t_now = gethrtime();
1419b690436dSAndreas Jaekel 			if (t_now < t_until) {
1420b690436dSAndreas Jaekel 				ms = t_until - t_now;
1421b690436dSAndreas Jaekel 				ms /= 1000000ull;
1422b690436dSAndreas Jaekel 			}
1423b690436dSAndreas Jaekel 			if (ret < 0) {
1424b690436dSAndreas Jaekel 				perror("poll failed");
1425b690436dSAndreas Jaekel 				close(q_fd);
1426b690436dSAndreas Jaekel 				return(EXIT_FAILURE);
1427b690436dSAndreas Jaekel 			}
1428b690436dSAndreas Jaekel 			if (!(pfd[0].revents & POLLIN))
1429b690436dSAndreas Jaekel 				continue;
1430b690436dSAndreas Jaekel 			/* data available */
1431b690436dSAndreas Jaekel 			ret = read(q_fd, buf, sizeof(buf));
1432b690436dSAndreas Jaekel 			if (ret < 0) {
1433b690436dSAndreas Jaekel 				perror("read failed");
1434b690436dSAndreas Jaekel 				close(q_fd);
1435b690436dSAndreas Jaekel 				return(EXIT_FAILURE);
1436b690436dSAndreas Jaekel 			}
1437b690436dSAndreas Jaekel 			if (ret == 0)
1438b690436dSAndreas Jaekel 				continue;
1439b690436dSAndreas Jaekel 			while (ret > off) {
1440b690436dSAndreas Jaekel 				ev = (zev_event_t *)(buf + off);
1441b690436dSAndreas Jaekel 				zev_eventstat(buf + off, ev->header.record_len);
1442b690436dSAndreas Jaekel 				off += ev->header.record_len;
1443b690436dSAndreas Jaekel 			}
1444b690436dSAndreas Jaekel 			off = 0;
1445b690436dSAndreas Jaekel 		} while ((t_now) < t_until && (ms > 0));
1446f432e238SAndreas Jaekel 		zev_eventstat_interval(out);
1447b690436dSAndreas Jaekel 		if (cnt > 0)
1448b690436dSAndreas Jaekel 			cnt--;
1449b690436dSAndreas Jaekel 	}
1450b690436dSAndreas Jaekel 	close(q_fd);
1451f432e238SAndreas Jaekel 	if (outfile)
1452f432e238SAndreas Jaekel 		fclose(out);
1453b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
1454b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
1455b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_runtime)) {
1456b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_runtime, gt);
1457b690436dSAndreas Jaekel 		free(gt);
1458b690436dSAndreas Jaekel 	}
1459b690436dSAndreas Jaekel 	return EXIT_SUCCESS;
1460b690436dSAndreas Jaekel }
1461b690436dSAndreas Jaekel 
1462f432e238SAndreas Jaekel static int
1463f432e238SAndreas Jaekel zev_report(int fd, char *basename)
1464f432e238SAndreas Jaekel {
1465f432e238SAndreas Jaekel 	char filename[MAXPATHLEN];
1466f432e238SAndreas Jaekel 	char count[10];
1467f432e238SAndreas Jaekel 	time_t now;
1468f432e238SAndreas Jaekel 	time_t midnight;
1469f432e238SAndreas Jaekel 	struct tm tm;
1470f432e238SAndreas Jaekel 	int minutes;
1471f432e238SAndreas Jaekel 	int ret;
1472f432e238SAndreas Jaekel 
1473f432e238SAndreas Jaekel 	verbose++;
1474f432e238SAndreas Jaekel 	while (1) {
1475f432e238SAndreas Jaekel 		now = time(NULL);
1476f432e238SAndreas Jaekel 		localtime_r(&now, &tm);
1477f432e238SAndreas Jaekel 		snprintf(filename, sizeof(filename), "%s.%04d-%02d-%02d",
1478f432e238SAndreas Jaekel 		         basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
1479f432e238SAndreas Jaekel 		tm.tm_sec = 0;
1480f432e238SAndreas Jaekel 		tm.tm_min = 0;
1481f432e238SAndreas Jaekel 		tm.tm_hour = 0;
1482f432e238SAndreas Jaekel 		tm.tm_mday++;  /* works for Jan 32nd, Feb 30th, etc. */
1483f432e238SAndreas Jaekel 		midnight = mktime(&tm);
1484f432e238SAndreas Jaekel 		if (now % 60)
1485f432e238SAndreas Jaekel 			sleep(60 - (now % 60));
1486f432e238SAndreas Jaekel 		minutes = (midnight - time(NULL)) / 60;
1487f432e238SAndreas Jaekel 		snprintf(count, sizeof(count), "%d", minutes);
1488f432e238SAndreas Jaekel 		ret = zev_zevstat(fd, "60", count, filename);
1489f432e238SAndreas Jaekel 		if (ret)
1490f432e238SAndreas Jaekel 			return EXIT_FAILURE;
1491f432e238SAndreas Jaekel 	}
1492f432e238SAndreas Jaekel 	return EXIT_SUCCESS; /* never reached */
1493f432e238SAndreas Jaekel }
1494f432e238SAndreas Jaekel 
1495*a0d677d8SAndreas Jaekel static void
1496*a0d677d8SAndreas Jaekel zev_sigint(int sig)
1497*a0d677d8SAndreas Jaekel {
1498*a0d677d8SAndreas Jaekel 	fflush(stdout);
1499*a0d677d8SAndreas Jaekel }
1500*a0d677d8SAndreas Jaekel 
1501a18c35b9SAndreas Jaekel int
1502a18c35b9SAndreas Jaekel main(int argc, char **argv)
1503a18c35b9SAndreas Jaekel {
1504a18c35b9SAndreas Jaekel 	int fd;
1505a18c35b9SAndreas Jaekel 	int c;
1506a18c35b9SAndreas Jaekel 	extern char *optarg;
15076a6a51eeSAndreas Jaekel 	int create_tmp_queue = 1;
15086a6a51eeSAndreas Jaekel 	char buf[MAXPATHLEN];
1509a5090b97SAndreas Jaekel 	int mode = 0;
1510a5090b97SAndreas Jaekel 	char *arg = NULL;
1511a5090b97SAndreas Jaekel 	char *arg2 = NULL;
1512b690436dSAndreas Jaekel 	char *p;
1513b690436dSAndreas Jaekel 
1514*a0d677d8SAndreas Jaekel 	sigset(SIGINT, zev_sigint);
1515*a0d677d8SAndreas Jaekel 
151650da9edeSAndreas Jaekel 	/* open device */
151750da9edeSAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
151850da9edeSAndreas Jaekel 	if (fd < 0) {
151950da9edeSAndreas Jaekel 		perror("opening zev device failed");
152050da9edeSAndreas Jaekel 		return EXIT_FAILURE;
152150da9edeSAndreas Jaekel 	}
152250da9edeSAndreas Jaekel 
1523b690436dSAndreas Jaekel 	p = strrchr(argv[0], '/');
1524b690436dSAndreas Jaekel 	if (!p) {
1525b690436dSAndreas Jaekel 		p = argv[0];
1526b690436dSAndreas Jaekel 	} else {
1527b690436dSAndreas Jaekel 		p++;
1528b690436dSAndreas Jaekel 	}
1529b690436dSAndreas Jaekel 	if (!strcmp(p, "zevstat")) {
1530b690436dSAndreas Jaekel 		mode = MD_ZEVSTAT;
153150da9edeSAndreas Jaekel 		if (argc < 2)
153250da9edeSAndreas Jaekel 			zevstat_usage(argv[0]);
153350da9edeSAndreas Jaekel 		if (!strcmp(argv[1], "-v")) {
153450da9edeSAndreas Jaekel 			if (argc < 3)
153550da9edeSAndreas Jaekel 				zevstat_usage(argv[0]);
153650da9edeSAndreas Jaekel 			verbose++;
153750da9edeSAndreas Jaekel 			arg = argv[2];
153850da9edeSAndreas Jaekel 			arg2 = argv[3];
153950da9edeSAndreas Jaekel 		} else {
154050da9edeSAndreas Jaekel 			arg = argv[1];
154150da9edeSAndreas Jaekel 			arg2 = argv[2];
154250da9edeSAndreas Jaekel 		}
1543f432e238SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
1544f432e238SAndreas Jaekel 	} else if(!strcmp(p, "zevreport")) {
1545f432e238SAndreas Jaekel 		mode = MD_ZEV_REPORT;
1546f432e238SAndreas Jaekel 		if (argc != 2)
1547f432e238SAndreas Jaekel 			zevreport_usage(argv[0]);
1548f432e238SAndreas Jaekel 		return zev_report(fd, argv[1]);
1549b690436dSAndreas Jaekel 	}
1550a18c35b9SAndreas Jaekel 
15516a6a51eeSAndreas Jaekel 	while ((c = getopt(argc, argv,
1552174dc952SAndreas Jaekel 	                   "gvspc:d:Dlk:L:q:Q:t:m:M:a:A:r:P:b:B:T:R:h?")) != -1){
1553a18c35b9SAndreas Jaekel 		switch(c) {
155416ff6b2fSAndreas Jaekel 		case 'g':
155516ff6b2fSAndreas Jaekel 			grep_friendly++;
155616ff6b2fSAndreas Jaekel 			verbose++;
155716ff6b2fSAndreas Jaekel 			break;
1558205ed6bfSAndreas Jaekel 		case 'v':
1559205ed6bfSAndreas Jaekel 			verbose++;
1560205ed6bfSAndreas Jaekel 			break;
1561a18c35b9SAndreas Jaekel 		case 's':
1562a5090b97SAndreas Jaekel 			mode = MD_STATISTICS;
1563a5090b97SAndreas Jaekel 			break;
1564a18c35b9SAndreas Jaekel 		case 'p':
1565a5090b97SAndreas Jaekel 			mode = MD_POLL_EVENTS;
1566a5090b97SAndreas Jaekel 			break;
156742110aacSAndreas Jaekel 		case 'c':
1568a5090b97SAndreas Jaekel 			mode = MD_CHECKSUMS;
1569a5090b97SAndreas Jaekel 			arg = optarg;
1570a5090b97SAndreas Jaekel 			break;
1571add9520fSAndreas Jaekel 		case 'D':
1572a5090b97SAndreas Jaekel 			mode = MD_DEBUG_INFO;
1573a5090b97SAndreas Jaekel 			break;
1574a18c35b9SAndreas Jaekel 		case 'd':
1575add9520fSAndreas Jaekel 			close(fd);
1576a18c35b9SAndreas Jaekel 			zev_device = optarg;
1577add9520fSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1578add9520fSAndreas Jaekel 			if (fd < 0) {
1579add9520fSAndreas Jaekel 				perror("opening zev device failed");
1580add9520fSAndreas Jaekel 				return EXIT_FAILURE;
1581add9520fSAndreas Jaekel 			}
15826a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
15836a6a51eeSAndreas Jaekel 			break;
15846a6a51eeSAndreas Jaekel 		case 'q':
15856a6a51eeSAndreas Jaekel 			snprintf(buf, sizeof(buf),
15866a6a51eeSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
15876a6a51eeSAndreas Jaekel 			close(fd);
15886a6a51eeSAndreas Jaekel 			zev_device = buf;
15896a6a51eeSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
15906a6a51eeSAndreas Jaekel 			if (fd < 0) {
15916a6a51eeSAndreas Jaekel 				perror("opening zev device failed");
15926a6a51eeSAndreas Jaekel 				return EXIT_FAILURE;
15936a6a51eeSAndreas Jaekel 			}
15946a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
1595a18c35b9SAndreas Jaekel 			break;
1596add9520fSAndreas Jaekel 		case 'l':
1597a5090b97SAndreas Jaekel 			mode = MD_LIST_QUEUES;
1598a5090b97SAndreas Jaekel 			break;
1599add9520fSAndreas Jaekel 		case 'Q':
1600a5090b97SAndreas Jaekel 			mode = MD_SET_GLOBAL_MAX_QUEUE_LEN;
1601a5090b97SAndreas Jaekel 			arg = optarg;
1602a5090b97SAndreas Jaekel 			break;
16036a6a51eeSAndreas Jaekel 		case 'L':
1604a5090b97SAndreas Jaekel 			mode = MD_SET_MAX_QUEUE_LEN;
1605a5090b97SAndreas Jaekel 			arg = optarg;
1606a5090b97SAndreas Jaekel 			arg2 = argv[optind];
1607a5090b97SAndreas Jaekel 			break;
1608b690436dSAndreas Jaekel 		case 'T':
1609b690436dSAndreas Jaekel 			mode = MD_ZEVSTAT;
1610b690436dSAndreas Jaekel 			arg = optarg;
1611b690436dSAndreas Jaekel 			arg2 = argv[optind];
1612b690436dSAndreas Jaekel 			break;
1613f432e238SAndreas Jaekel 		case 'R':
1614f432e238SAndreas Jaekel 			mode = MD_ZEV_REPORT;
1615f432e238SAndreas Jaekel 			arg = optarg;
1616f432e238SAndreas Jaekel 			break;
1617fec460f8SAndreas Jaekel 		case 't':
1618a5090b97SAndreas Jaekel 			mode = MD_SET_POLL_WAKEUP_QUEUE_LEN;
1619a5090b97SAndreas Jaekel 			arg = optarg;
1620a5090b97SAndreas Jaekel 			arg2 = argv[optind];
1621a5090b97SAndreas Jaekel 			break;
1622a18c35b9SAndreas Jaekel 		case 'm':
1623a5090b97SAndreas Jaekel 			mode = MD_MUTE_POOL;
1624a5090b97SAndreas Jaekel 			arg = optarg;
1625a5090b97SAndreas Jaekel 			break;
1626a18c35b9SAndreas Jaekel 		case 'M':
1627a5090b97SAndreas Jaekel 			mode = MD_UNMUTE_POOL;
1628a5090b97SAndreas Jaekel 			arg = optarg;
1629a5090b97SAndreas Jaekel 			break;
1630888fea18SAndreas Jaekel 		case 'k':
1631a5090b97SAndreas Jaekel 			mode = MD_MARK;
1632a5090b97SAndreas Jaekel 			arg = optarg;
1633a5090b97SAndreas Jaekel 			break;
1634add9520fSAndreas Jaekel 		case 'a':
1635a5090b97SAndreas Jaekel 			mode = MD_ADD_QUEUE;
1636a5090b97SAndreas Jaekel 			arg = optarg;
1637a5090b97SAndreas Jaekel 			break;
16386a6a51eeSAndreas Jaekel 		case 'A':
1639a5090b97SAndreas Jaekel 			mode = MD_ADD_BLOCKING_QUEUE;
1640a5090b97SAndreas Jaekel 			arg = optarg;
1641a5090b97SAndreas Jaekel 			break;
1642add9520fSAndreas Jaekel 		case 'r':
1643a5090b97SAndreas Jaekel 			mode = MD_REMOVE_QUEUE;
1644a5090b97SAndreas Jaekel 			arg = optarg;
1645a5090b97SAndreas Jaekel 			break;
1646add9520fSAndreas Jaekel 		case 'b':
1647a5090b97SAndreas Jaekel 			mode = MD_QUEUE_BLOCKING;
1648a5090b97SAndreas Jaekel 			arg = optarg;
1649a5090b97SAndreas Jaekel 			break;
1650add9520fSAndreas Jaekel 		case 'B':
1651a5090b97SAndreas Jaekel 			mode = MD_QUEUE_NONBLOCKING;
1652a5090b97SAndreas Jaekel 			arg = optarg;
1653a5090b97SAndreas Jaekel 			break;
1654add9520fSAndreas Jaekel 		case 'P':
1655a5090b97SAndreas Jaekel 			mode = MD_QUEUE_PROPERTIES;
1656a5090b97SAndreas Jaekel 			arg = optarg;
1657a5090b97SAndreas Jaekel 			break;
1658a18c35b9SAndreas Jaekel 		case 'h':
1659a18c35b9SAndreas Jaekel 		case '?':
1660a18c35b9SAndreas Jaekel 		default:
1661a18c35b9SAndreas Jaekel 			usage(argv[0]);
1662a18c35b9SAndreas Jaekel 		}
1663a18c35b9SAndreas Jaekel 	}
1664a5090b97SAndreas Jaekel 
1665a5090b97SAndreas Jaekel 	switch (mode) {
1666a5090b97SAndreas Jaekel 	case MD_STATISTICS:
1667a5090b97SAndreas Jaekel 		return zev_statistics(fd);
1668a5090b97SAndreas Jaekel 	case MD_POLL_EVENTS:
1669a5090b97SAndreas Jaekel 		return zev_poll_events(fd, create_tmp_queue);
1670a5090b97SAndreas Jaekel 	case MD_CHECKSUMS:
1671a5090b97SAndreas Jaekel 		return zev_checksum(fd, arg);
1672a5090b97SAndreas Jaekel 	case MD_DEBUG_INFO:
1673a5090b97SAndreas Jaekel 		return zev_debug_info(fd);
1674a5090b97SAndreas Jaekel 	case MD_LIST_QUEUES:
1675a5090b97SAndreas Jaekel 		return zev_list_queues(fd);
1676a5090b97SAndreas Jaekel 	case MD_SET_GLOBAL_MAX_QUEUE_LEN:
1677a5090b97SAndreas Jaekel 		return zev_set_global_max_queue_len(fd, arg);
1678a5090b97SAndreas Jaekel 	case MD_SET_MAX_QUEUE_LEN:
1679a5090b97SAndreas Jaekel 		return zev_set_max_queue_len(fd, arg, arg2);
1680a5090b97SAndreas Jaekel 	case MD_SET_POLL_WAKEUP_QUEUE_LEN:
1681a5090b97SAndreas Jaekel 		return zev_set_poll_wakeup_queue_len(fd, arg, arg2);
1682b690436dSAndreas Jaekel 	case MD_ZEVSTAT:
1683f432e238SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
1684f432e238SAndreas Jaekel 	case MD_ZEV_REPORT:
1685f432e238SAndreas Jaekel 		return zev_report(fd, arg);
1686a5090b97SAndreas Jaekel 	case MD_MUTE_POOL:
1687a5090b97SAndreas Jaekel 		return zev_mute_pool(fd, arg);
1688a5090b97SAndreas Jaekel 	case MD_UNMUTE_POOL:
1689a5090b97SAndreas Jaekel 		return zev_unmute_pool(fd, arg);
1690a5090b97SAndreas Jaekel 	case MD_MARK:
1691a5090b97SAndreas Jaekel 		return zev_mark(fd, arg);
1692a5090b97SAndreas Jaekel 	case MD_ADD_QUEUE:
1693a5090b97SAndreas Jaekel 		return zev_add_queue(fd, arg, 0);
1694a5090b97SAndreas Jaekel 	case MD_ADD_BLOCKING_QUEUE:
1695a5090b97SAndreas Jaekel 		return zev_add_queue(fd, arg, 1);
1696a5090b97SAndreas Jaekel 	case MD_REMOVE_QUEUE:
1697a5090b97SAndreas Jaekel 		return zev_remove_queue(fd, arg);
1698a5090b97SAndreas Jaekel 	case MD_QUEUE_BLOCKING:
1699a5090b97SAndreas Jaekel 		return zev_queue_blocking(fd, arg, 0);
1700a5090b97SAndreas Jaekel 	case MD_QUEUE_NONBLOCKING:
1701a5090b97SAndreas Jaekel 		return zev_queue_blocking(fd, arg, 1);
1702a5090b97SAndreas Jaekel 	case MD_QUEUE_PROPERTIES:
1703a5090b97SAndreas Jaekel 		return zev_queue_properties(fd, arg);
1704a5090b97SAndreas Jaekel 	default:
1705a18c35b9SAndreas Jaekel 		close(fd);
1706a5090b97SAndreas Jaekel 		usage(argv[0]);
1707add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1708a5090b97SAndreas Jaekel 	};
1709a18c35b9SAndreas Jaekel }
1710a18c35b9SAndreas Jaekel 
1711