xref: /titanic_50/usr/src/cmd/zevadm/zevadm.c (revision c07f6d81c2aa306946e0502fe7c11e81c47ab13a)
12bb8e5e2SAndreas Jaekel #include <stdio.h>
22bb8e5e2SAndreas Jaekel #include <unistd.h>
32bb8e5e2SAndreas Jaekel #include <stdlib.h>
42bb8e5e2SAndreas Jaekel #include <fcntl.h>
52bb8e5e2SAndreas Jaekel #include <stropts.h>
62bb8e5e2SAndreas Jaekel #include <poll.h>
72bb8e5e2SAndreas Jaekel #include <string.h>
82bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h>
92bb8e5e2SAndreas Jaekel #include <errno.h>
10b9710123SAndreas Jaekel #include <sys/sysmacros.h>
11d65b2fffSAndreas Jaekel #include <stdarg.h>
120abdde4aSAndreas Jaekel #include <sys/avl.h>
139fd83c76SAndreas Jaekel #include <sys/stat.h>
142bb8e5e2SAndreas Jaekel 
15e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
162bb8e5e2SAndreas Jaekel 
170abdde4aSAndreas Jaekel #if !defined(offsetof)
180abdde4aSAndreas Jaekel #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
190abdde4aSAndreas Jaekel #endif
200abdde4aSAndreas Jaekel 
212bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
22*c07f6d81SArne Jansen static int do_flush = 0;
232bb8e5e2SAndreas Jaekel 
249193e9c2SAndreas Jaekel static char *zev_op_name[] = {
25d65b2fffSAndreas Jaekel 	"ERROR",
26d65b2fffSAndreas Jaekel 	"MARK",
27d65b2fffSAndreas Jaekel 	"ZFS_MOUNT",
28d65b2fffSAndreas Jaekel 	"ZFS_UMOUNT",
29d65b2fffSAndreas Jaekel 	"ZVOL_WRITE",
30d65b2fffSAndreas Jaekel 	"ZVOL_TRUNCATE",
31d65b2fffSAndreas Jaekel 	"ZNODE_CLOSE_AFTER_UPDATE",
32d65b2fffSAndreas Jaekel 	"ZNODE_CREATE",
33d65b2fffSAndreas Jaekel 	"ZNODE_MKDIR",
34d65b2fffSAndreas Jaekel 	"ZNODE_MAKE_XATTR_DIR",
35d65b2fffSAndreas Jaekel 	"ZNODE_REMOVE",
36d65b2fffSAndreas Jaekel 	"ZNODE_RMDIR",
37d65b2fffSAndreas Jaekel 	"ZNODE_LINK",
38d65b2fffSAndreas Jaekel 	"ZNODE_SYMLINK",
39d65b2fffSAndreas Jaekel 	"ZNODE_RENAME",
40d65b2fffSAndreas Jaekel 	"ZNODE_WRITE",
41d65b2fffSAndreas Jaekel 	"ZNODE_TRUNCATE",
42d65b2fffSAndreas Jaekel 	"ZNODE_SETATTR",
43d65b2fffSAndreas Jaekel 	"ZNODE_ACL",
449193e9c2SAndreas Jaekel 	NULL
459193e9c2SAndreas Jaekel };
469193e9c2SAndreas Jaekel 
476a3d43bfSAndreas Jaekel #define MD_STATISTICS			1
486a3d43bfSAndreas Jaekel #define MD_POLL_EVENTS			2
496a3d43bfSAndreas Jaekel #define MD_CHECKSUMS			3
506a3d43bfSAndreas Jaekel #define MD_DEBUG_INFO			4
516a3d43bfSAndreas Jaekel #define MD_LIST_QUEUES			5
526a3d43bfSAndreas Jaekel #define MD_SET_GLOBAL_MAX_QUEUE_LEN	6
536a3d43bfSAndreas Jaekel #define MD_SET_MAX_QUEUE_LEN		7
546a3d43bfSAndreas Jaekel #define MD_SET_POLL_WAKEUP_QUEUE_LEN	8
556a3d43bfSAndreas Jaekel #define MD_MUTE_POOL			9
566a3d43bfSAndreas Jaekel #define MD_UNMUTE_POOL			10
576a3d43bfSAndreas Jaekel #define MD_MARK				11
586a3d43bfSAndreas Jaekel #define MD_ADD_QUEUE			12
596a3d43bfSAndreas Jaekel #define MD_ADD_BLOCKING_QUEUE		13
606a3d43bfSAndreas Jaekel #define MD_REMOVE_QUEUE			14
616a3d43bfSAndreas Jaekel #define MD_QUEUE_BLOCKING		15
626a3d43bfSAndreas Jaekel #define MD_QUEUE_NONBLOCKING		16
636a3d43bfSAndreas Jaekel #define MD_QUEUE_PROPERTIES		17
640abdde4aSAndreas Jaekel #define MD_ZEVSTAT			18
659fd83c76SAndreas Jaekel #define MD_ZEV_REPORT			19
66797b8adfSArne Jansen #define MD_DUMP_SPOOL			20
67c62d8367SAndreas Jaekel #define MD_GET_ZEV_VERSION		21
686a3d43bfSAndreas Jaekel 
695e286361SAndreas Jaekel static int verbose = 0;
70d65b2fffSAndreas Jaekel static int grep_friendly = 0;
71d65b2fffSAndreas Jaekel 
72d65b2fffSAndreas Jaekel static void
73d65b2fffSAndreas Jaekel zpf(char *fmt, ...)
74d65b2fffSAndreas Jaekel {
75d65b2fffSAndreas Jaekel 	va_list	ap;
76d65b2fffSAndreas Jaekel 
77d65b2fffSAndreas Jaekel 	va_start(ap, fmt);
78d65b2fffSAndreas Jaekel 	vprintf(fmt, ap);
79d65b2fffSAndreas Jaekel 	va_end(ap);
80d65b2fffSAndreas Jaekel 	if (grep_friendly) {
81d65b2fffSAndreas Jaekel 		printf(" ");
82d65b2fffSAndreas Jaekel 	} else {
83d65b2fffSAndreas Jaekel 		printf("\n");
84d65b2fffSAndreas Jaekel 	}
85d65b2fffSAndreas Jaekel }
86d65b2fffSAndreas Jaekel 
87d65b2fffSAndreas Jaekel static void
88d65b2fffSAndreas Jaekel znl(void)
89d65b2fffSAndreas Jaekel {
90d65b2fffSAndreas Jaekel 	if (grep_friendly)
91d65b2fffSAndreas Jaekel 		printf("\n");
92d65b2fffSAndreas Jaekel }
935e286361SAndreas Jaekel 
941ca5a13bSAndreas Jaekel static void
951ca5a13bSAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
961ca5a13bSAndreas Jaekel {
971ca5a13bSAndreas Jaekel 	int     i;
981ca5a13bSAndreas Jaekel 
991ca5a13bSAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
1001ca5a13bSAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
1011ca5a13bSAndreas Jaekel 	}
1021ca5a13bSAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
1031ca5a13bSAndreas Jaekel }
1041ca5a13bSAndreas Jaekel 
105e9a5e479SAndreas Jaekel static int
1062bb8e5e2SAndreas Jaekel zev_statistics(int fd)
1072bb8e5e2SAndreas Jaekel {
1082bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
109e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
1102bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
111e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1122bb8e5e2SAndreas Jaekel 	}
1132bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
1142bb8e5e2SAndreas Jaekel 
1152bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
1162bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
1172bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
1182bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
1192bb8e5e2SAndreas Jaekel 
120e9a5e479SAndreas Jaekel 	printf("    discarded events        : %lu\n",
121e9a5e479SAndreas Jaekel 	    zs.zev_cnt_discarded_events);
122e9a5e479SAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
123e9a5e479SAndreas Jaekel 
1242bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
1252bb8e5e2SAndreas Jaekel 
1262bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
1272bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
1282bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
1292bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
1302bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
1312bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
1322bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
1332bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
1342bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
1352bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
1362bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
1372bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
1382bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
1392bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
1402bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
1412bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
1422bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
143e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
1442bb8e5e2SAndreas Jaekel }
1452bb8e5e2SAndreas Jaekel 
1462bb8e5e2SAndreas Jaekel static void
147d65b2fffSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info)
148d65b2fffSAndreas Jaekel {
149d65b2fffSAndreas Jaekel 	zpf("  %s.inode: %llu", name, info->ino);
150d65b2fffSAndreas Jaekel 	zpf("  %s.gen: %llu", name, info->gen);
151d65b2fffSAndreas Jaekel 	zpf("  %s.mtime: %llu", name, info->mtime);
152d65b2fffSAndreas Jaekel 	zpf("  %s.ctime: %llu", name, info->ctime);
153d65b2fffSAndreas Jaekel 	zpf("  %s.size: %llu", name, info->size);
154d65b2fffSAndreas Jaekel 	zpf("  %s.mode: %llo", name, info->mode);
155d65b2fffSAndreas Jaekel 	zpf("  %s.links: %llu", name, info->links);
156d65b2fffSAndreas Jaekel 	zpf("  %s.type: %lu", name, info->type);
157d65b2fffSAndreas Jaekel 	zpf("  %s.flags: %lu", name, info->flags);
158d65b2fffSAndreas Jaekel }
159d65b2fffSAndreas Jaekel 
160d65b2fffSAndreas Jaekel static void
161d65b2fffSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec)
162d65b2fffSAndreas Jaekel {
163d65b2fffSAndreas Jaekel 	int i;
164d65b2fffSAndreas Jaekel 	int j;
165d65b2fffSAndreas Jaekel 	uint8_t *p;
166d65b2fffSAndreas Jaekel 	char c;
167d65b2fffSAndreas Jaekel 
168d65b2fffSAndreas Jaekel 	zpf("  payload:");
169d65b2fffSAndreas Jaekel 	p = (uint8_t *)ZEV_PAYLOAD(rec);
170d65b2fffSAndreas Jaekel 	for (i=0; i<rec->payload_len; i+=16) {
171d65b2fffSAndreas Jaekel 		printf("  ");
172d65b2fffSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
173d65b2fffSAndreas Jaekel 			printf("%02x ", p[j]);
174d65b2fffSAndreas Jaekel 			if (j == i + 7)
175d65b2fffSAndreas Jaekel 				printf(" ");
176d65b2fffSAndreas Jaekel 		}
177d65b2fffSAndreas Jaekel 		if (grep_friendly)
178d65b2fffSAndreas Jaekel 			continue;
179d65b2fffSAndreas Jaekel 		for (; j<i+16; j++) {
180d65b2fffSAndreas Jaekel 			printf("   ");
181d65b2fffSAndreas Jaekel 			if (j == i + 7)
182d65b2fffSAndreas Jaekel 				printf(" ");
183d65b2fffSAndreas Jaekel 		}
184d65b2fffSAndreas Jaekel 		printf("    ");
185d65b2fffSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
186d65b2fffSAndreas Jaekel 			c = '.';
187d65b2fffSAndreas Jaekel 			if (p[j] >= ' ' && p[j] <= '~')
188d65b2fffSAndreas Jaekel 				c = p[j];
189d65b2fffSAndreas Jaekel 			printf("%c", c);
190d65b2fffSAndreas Jaekel 			if (j == i + 7)
191d65b2fffSAndreas Jaekel 				printf(" ");
192d65b2fffSAndreas Jaekel 		}
193d65b2fffSAndreas Jaekel 		printf("\n");
194d65b2fffSAndreas Jaekel 	}
195d65b2fffSAndreas Jaekel }
196d65b2fffSAndreas Jaekel 
197d65b2fffSAndreas Jaekel static void
19863aba447SAndreas Jaekel zev_print_error(char *buf)
19963aba447SAndreas Jaekel {
20063aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
20163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
20263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
20363aba447SAndreas Jaekel 
204d65b2fffSAndreas Jaekel 	if (verbose) {
205d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
206d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
207d65b2fffSAndreas Jaekel 		zpf("  failed.op: %s",
208d65b2fffSAndreas Jaekel 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
209d65b2fffSAndreas Jaekel 		zpf("  message: %s", ZEV_ERRSTR(rec));
210d65b2fffSAndreas Jaekel 		znl();
211d65b2fffSAndreas Jaekel 	} else {
21263aba447SAndreas Jaekel 		printf("%s %s: failed_op=%s msg=%s\n",
21363aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
214d65b2fffSAndreas Jaekel 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
215d65b2fffSAndreas Jaekel 		       ZEV_ERRSTR(rec));
216d65b2fffSAndreas Jaekel 	}
21763aba447SAndreas Jaekel }
21863aba447SAndreas Jaekel 
21963aba447SAndreas Jaekel static void
22001c2c787SAndreas Jaekel zev_print_mark(char *buf)
22101c2c787SAndreas Jaekel {
22201c2c787SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
22301c2c787SAndreas Jaekel 	time_t op_time = rec->op_time;
22401c2c787SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
22501c2c787SAndreas Jaekel 
226d65b2fffSAndreas Jaekel 	if (verbose) {
227d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
228d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
229d65b2fffSAndreas Jaekel 		zpf("  mark.id: %llu", rec->mark_id);
230d65b2fffSAndreas Jaekel 		zpf("  payload.len: %llu", rec->payload_len);
231d65b2fffSAndreas Jaekel 		if (rec->payload_len)
232d65b2fffSAndreas Jaekel 			zev_print_mark_payload(rec);
233d65b2fffSAndreas Jaekel 		znl();
234d65b2fffSAndreas Jaekel 	} else {
23557340784SJan Schlien 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld "
23657340784SJan Schlien 		       "payload=\"%.*s\"\n",
237d65b2fffSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
23857340784SJan Schlien 		       rec->mark_id, rec->payload_len,
23957340784SJan Schlien 		       rec->payload_len, (char *)(rec + 1));
240d65b2fffSAndreas Jaekel 	}
24101c2c787SAndreas Jaekel }
24201c2c787SAndreas Jaekel 
24301c2c787SAndreas Jaekel static void
24463aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
24563aba447SAndreas Jaekel {
24663aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
24763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
24863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
24963aba447SAndreas Jaekel 
250d65b2fffSAndreas Jaekel 	if (verbose) {
251d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
252d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
253d3b66d30SSimon Klinkert 		zpf("  txg: %llu", rec->txg);
254d65b2fffSAndreas Jaekel 		zpf("  dataset: %s", ZEV_DATASET(rec));
255d65b2fffSAndreas Jaekel 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
256d65b2fffSAndreas Jaekel 		zpf("  remount: %s", rec->remount ? "true" : "false");
257d65b2fffSAndreas Jaekel 		zev_print_inode_info("root", &rec->root);
258d65b2fffSAndreas Jaekel 		znl();
259d65b2fffSAndreas Jaekel 	} else {
260d65b2fffSAndreas Jaekel 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
261d65b2fffSAndreas Jaekel 		       "mountpoint='%s'\n",
26263aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
26363aba447SAndreas Jaekel 		       rec->guid,
26463aba447SAndreas Jaekel 		       rec->remount ? "true" : "false",
26563aba447SAndreas Jaekel 		       ZEV_DATASET(rec),
26663aba447SAndreas Jaekel 		       ZEV_MOUNTPOINT(rec));
26763aba447SAndreas Jaekel 	}
268d65b2fffSAndreas Jaekel }
26963aba447SAndreas Jaekel 
27063aba447SAndreas Jaekel static void
27163aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
27263aba447SAndreas Jaekel {
27363aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
27463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
27563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
27663aba447SAndreas Jaekel 
277d65b2fffSAndreas Jaekel 	if (verbose) {
278d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
279d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
280d3b66d30SSimon Klinkert 		zpf("  txg: %llu", rec->txg);
281443f0cd2SAndreas Jaekel 		zev_print_inode_info("covered", &rec->covered);
282d65b2fffSAndreas Jaekel 		znl();
283d65b2fffSAndreas Jaekel 	} else {
28463aba447SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
28563aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
28663aba447SAndreas Jaekel 		       rec->guid);
28763aba447SAndreas Jaekel 	}
288d65b2fffSAndreas Jaekel }
28963aba447SAndreas Jaekel 
29063aba447SAndreas Jaekel static void
29163aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
29263aba447SAndreas Jaekel {
29363aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
29463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
29563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
29663aba447SAndreas Jaekel 
297d65b2fffSAndreas Jaekel 	if (verbose) {
298d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
299d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
300e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
301d65b2fffSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
302d65b2fffSAndreas Jaekel 		zpf("  length: %llu", rec->length);
303d65b2fffSAndreas Jaekel 		znl();
304d65b2fffSAndreas Jaekel 	} else {
30563aba447SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
30663aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
30763aba447SAndreas Jaekel 		       rec->guid,
30863aba447SAndreas Jaekel 		       rec->offset,
30963aba447SAndreas Jaekel 		       rec->length);
31063aba447SAndreas Jaekel 	}
311d65b2fffSAndreas Jaekel }
31263aba447SAndreas Jaekel 
31363aba447SAndreas Jaekel static void
31463aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
31563aba447SAndreas Jaekel {
31663aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
31763aba447SAndreas Jaekel }
31863aba447SAndreas Jaekel 
31963aba447SAndreas Jaekel static void
32063aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
32163aba447SAndreas Jaekel {
32263aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
32363aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
32463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
32563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
32663aba447SAndreas Jaekel 
327d65b2fffSAndreas Jaekel 	if (verbose) {
328d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
329d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
330d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
331d65b2fffSAndreas Jaekel 		znl();
332d65b2fffSAndreas Jaekel 	} else {
33363aba447SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
33463aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
33563aba447SAndreas Jaekel 		       rec->guid,
33663aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
33763aba447SAndreas Jaekel 	}
338d65b2fffSAndreas Jaekel }
33963aba447SAndreas Jaekel 
34063aba447SAndreas Jaekel static void
34163aba447SAndreas Jaekel zev_print_znode_create(char *buf)
34263aba447SAndreas Jaekel {
34363aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
34463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
34563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
3461ca5a13bSAndreas Jaekel 	zev_sig_t *sig;
3471ca5a13bSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
34863aba447SAndreas Jaekel 
349d65b2fffSAndreas Jaekel 	if (verbose) {
350d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
351d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
352e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
353d65b2fffSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
3541ca5a13bSAndreas Jaekel 		sig = &rec->signature;
3551ca5a13bSAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
3561ca5a13bSAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
3571ca5a13bSAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
358d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
359e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
360d65b2fffSAndreas Jaekel 		znl();
361d65b2fffSAndreas Jaekel 	} else {
362c035b1e8SAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
363c035b1e8SAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
36463aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
36563aba447SAndreas Jaekel 		       rec->guid,
36663aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
36763aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
368c035b1e8SAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
36963aba447SAndreas Jaekel 		       ZEV_NAME(rec));
37063aba447SAndreas Jaekel 	}
371d65b2fffSAndreas Jaekel }
37263aba447SAndreas Jaekel 
37363aba447SAndreas Jaekel static void
37463aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
37563aba447SAndreas Jaekel {
37663aba447SAndreas Jaekel 	zev_print_znode_create(buf);
37763aba447SAndreas Jaekel }
37863aba447SAndreas Jaekel 
37963aba447SAndreas Jaekel static void
38063aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
38163aba447SAndreas Jaekel {
38263aba447SAndreas Jaekel 	zev_print_znode_create(buf);
38363aba447SAndreas Jaekel }
38463aba447SAndreas Jaekel 
38563aba447SAndreas Jaekel static void
38663aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
38763aba447SAndreas Jaekel {
38863aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
38963aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
39063aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
39163aba447SAndreas Jaekel 
392d65b2fffSAndreas Jaekel 	if (verbose) {
393d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
394d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
395e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
396d65b2fffSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
397d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
398e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
399d65b2fffSAndreas Jaekel 		znl();
400d65b2fffSAndreas Jaekel 	} else {
401d65b2fffSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
402d65b2fffSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
40363aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
40463aba447SAndreas Jaekel 		       rec->guid,
40563aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
4066db5d4ecSAndreas Jaekel 		       rec->file.mtime,
40763aba447SAndreas Jaekel 		       ZEV_NAME(rec));
40863aba447SAndreas Jaekel 	}
409d65b2fffSAndreas Jaekel }
41063aba447SAndreas Jaekel 
41163aba447SAndreas Jaekel static void
41263aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
41363aba447SAndreas Jaekel {
41463aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
41563aba447SAndreas Jaekel }
41663aba447SAndreas Jaekel 
41763aba447SAndreas Jaekel static void
41863aba447SAndreas Jaekel zev_print_znode_link(char *buf)
41963aba447SAndreas Jaekel {
42063aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
42163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
42263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
42363aba447SAndreas Jaekel 
424d65b2fffSAndreas Jaekel 	if (verbose) {
425d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
426d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
427e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
428d65b2fffSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
429d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
430e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
431d65b2fffSAndreas Jaekel 		znl();
432d65b2fffSAndreas Jaekel 	} else {
43303101f54SAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
43403101f54SAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
43563aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
43663aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
43763aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
43803101f54SAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
43963aba447SAndreas Jaekel 		       ZEV_NAME(rec));
440d65b2fffSAndreas Jaekel 	}
44163aba447SAndreas Jaekel }
44263aba447SAndreas Jaekel 
44363aba447SAndreas Jaekel static void
44463aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
44563aba447SAndreas Jaekel {
44663aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
44763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
44863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
4491ca5a13bSAndreas Jaekel 	zev_sig_t *sig;
4501ca5a13bSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
45163aba447SAndreas Jaekel 
452d65b2fffSAndreas Jaekel 	if (verbose) {
453d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
454d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
455e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
456d65b2fffSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
457d65b2fffSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
4581ca5a13bSAndreas Jaekel 		sig = &rec->signature;
4591ca5a13bSAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
4601ca5a13bSAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
4611ca5a13bSAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
462d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
463e206ace3SAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
464d65b2fffSAndreas Jaekel 		znl();
465d65b2fffSAndreas Jaekel 	} else {
466d65b2fffSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
467d65b2fffSAndreas Jaekel 		       "name='%s' link='%s'\n",
46863aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
46963aba447SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
47063aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
47163aba447SAndreas Jaekel 		       ZEV_NAME(rec),
47263aba447SAndreas Jaekel 		       ZEV_LINK(rec));
47363aba447SAndreas Jaekel 	}
474d65b2fffSAndreas Jaekel }
47563aba447SAndreas Jaekel 
47663aba447SAndreas Jaekel static void
47763aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
47863aba447SAndreas Jaekel {
47963aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
48063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
48163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
48263aba447SAndreas Jaekel 
483d65b2fffSAndreas Jaekel 	if (verbose) {
484d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
485d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
486e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
487d65b2fffSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
488d65b2fffSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
489d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
490f8e3fee2SAndreas Jaekel 		if (rec->clobbered_file.ino)
491f8e3fee2SAndreas Jaekel 			zev_print_inode_info("clobbered_file",
492f8e3fee2SAndreas Jaekel 			                     &rec->clobbered_file);
493d65b2fffSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
494d65b2fffSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
495d65b2fffSAndreas Jaekel 		znl();
496d65b2fffSAndreas Jaekel 	} else {
497d65b2fffSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
498d65b2fffSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
499d65b2fffSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
500d65b2fffSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
50163aba447SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
50263aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
50363aba447SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
50463aba447SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
50563aba447SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
506c035b1e8SAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
507c035b1e8SAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
508c035b1e8SAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
50963aba447SAndreas Jaekel 		       ZEV_SRCNAME(rec),
51063aba447SAndreas Jaekel 		       ZEV_DSTNAME(rec));
51163aba447SAndreas Jaekel 	}
512d65b2fffSAndreas Jaekel }
51363aba447SAndreas Jaekel 
51463aba447SAndreas Jaekel static void
51563aba447SAndreas Jaekel zev_print_znode_write(char *buf)
51663aba447SAndreas Jaekel {
51763aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
51863aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
51963aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
5205e286361SAndreas Jaekel 	zev_sig_t *sig;
5215e286361SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
5225e286361SAndreas Jaekel 	int i;
52363aba447SAndreas Jaekel 
5245e286361SAndreas Jaekel 	if (verbose) {
525d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
526d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
527e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
528d65b2fffSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
529d65b2fffSAndreas Jaekel 		zpf("  length: %llu", rec->length);
530d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
531d65b2fffSAndreas Jaekel 		znl();
5325e286361SAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
5335e286361SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
5345e286361SAndreas Jaekel 			sig += i;
5355e286361SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
5361ca5a13bSAndreas Jaekel 			zpf("  sig: level %d, offset %llu, value %s",
5375e286361SAndreas Jaekel 			    sig->level, sig->block_offset, sigval);
5385e286361SAndreas Jaekel 		}
539d65b2fffSAndreas Jaekel 	} else {
540d65b2fffSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
541d65b2fffSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
542d65b2fffSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
543d65b2fffSAndreas Jaekel 		       rec->offset, rec->length);
5445e286361SAndreas Jaekel 	}
54563aba447SAndreas Jaekel }
54663aba447SAndreas Jaekel 
54763aba447SAndreas Jaekel static void
54863aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
54963aba447SAndreas Jaekel {
55063aba447SAndreas Jaekel 	zev_print_znode_write(buf);
55163aba447SAndreas Jaekel }
55263aba447SAndreas Jaekel 
55363aba447SAndreas Jaekel static void
55463aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
55563aba447SAndreas Jaekel {
55663aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
55763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
55863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
55963aba447SAndreas Jaekel 
560d65b2fffSAndreas Jaekel 	if (verbose) {
561d65b2fffSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
562d65b2fffSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
563e206ace3SAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
564d65b2fffSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
565d65b2fffSAndreas Jaekel 		znl();
566d65b2fffSAndreas Jaekel 	} else {
567c035b1e8SAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
56863aba447SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
569c035b1e8SAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
57063aba447SAndreas Jaekel 	}
571d65b2fffSAndreas Jaekel }
57263aba447SAndreas Jaekel 
57363aba447SAndreas Jaekel static void
57463aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
57563aba447SAndreas Jaekel {
57663aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
57763aba447SAndreas Jaekel }
57863aba447SAndreas Jaekel 
57963aba447SAndreas Jaekel static void
5809193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
5819193e9c2SAndreas Jaekel {
58263aba447SAndreas Jaekel 	int record_len;
58363aba447SAndreas Jaekel 	int op;
5849193e9c2SAndreas Jaekel 
58563aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
58663aba447SAndreas Jaekel 	if (record_len != len) {
58763aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
58863aba447SAndreas Jaekel 		        record_len, len);
5899193e9c2SAndreas Jaekel 		exit(1);
5909193e9c2SAndreas Jaekel 	}
59163aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
5929193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
59363aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
5949193e9c2SAndreas Jaekel 		exit(1);
5959193e9c2SAndreas Jaekel 	}
59663aba447SAndreas Jaekel 	switch (op) {
59763aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
59863aba447SAndreas Jaekel 		zev_print_error(buf);
5999193e9c2SAndreas Jaekel 		break;
60001c2c787SAndreas Jaekel 	case ZEV_OP_MARK:
60101c2c787SAndreas Jaekel 		zev_print_mark(buf);
60201c2c787SAndreas Jaekel 		break;
60363aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
60463aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
6059193e9c2SAndreas Jaekel 		break;
60663aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
60763aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
6089193e9c2SAndreas Jaekel 		break;
60963aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
61063aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
6119193e9c2SAndreas Jaekel 		break;
61263aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
61363aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
61463aba447SAndreas Jaekel 		break;
61563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
61663aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
61763aba447SAndreas Jaekel 		break;
61863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
61963aba447SAndreas Jaekel 		zev_print_znode_create(buf);
62063aba447SAndreas Jaekel 		break;
62163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
62263aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
62363aba447SAndreas Jaekel 		break;
62463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
62563aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
62663aba447SAndreas Jaekel 		break;
62763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
62863aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
62963aba447SAndreas Jaekel 		break;
63063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
63163aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
63263aba447SAndreas Jaekel 		break;
63363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
63463aba447SAndreas Jaekel 		zev_print_znode_link(buf);
63563aba447SAndreas Jaekel 		break;
63663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
63763aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
63863aba447SAndreas Jaekel 		break;
63963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
64063aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
64163aba447SAndreas Jaekel 		break;
64263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
64363aba447SAndreas Jaekel 		zev_print_znode_write(buf);
64463aba447SAndreas Jaekel 		break;
64563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
64663aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
64763aba447SAndreas Jaekel 		break;
64863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
64963aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
65063aba447SAndreas Jaekel 		break;
65163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
65263aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
6539193e9c2SAndreas Jaekel 		break;
6549193e9c2SAndreas Jaekel 	default:
65563aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
6569193e9c2SAndreas Jaekel 		exit(1);
6579193e9c2SAndreas Jaekel 	}
658*c07f6d81SArne Jansen 	if (do_flush)
659*c07f6d81SArne Jansen 		fflush(stdout);
6609193e9c2SAndreas Jaekel }
6619193e9c2SAndreas Jaekel 
662e9a5e479SAndreas Jaekel static int
663bfe96c74SAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
6642bb8e5e2SAndreas Jaekel {
6652bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
6662bb8e5e2SAndreas Jaekel 	int ret;
6679193e9c2SAndreas Jaekel 	char buf[4096];
66868a46c64SAndreas Jaekel 	zev_event_t *ev;
66968a46c64SAndreas Jaekel 	int off = 0;
670e9a5e479SAndreas Jaekel 	int q_fd;
671e9a5e479SAndreas Jaekel 
6724ca7dd5eSAndreas Jaekel 	if (create_tmp_queue) {
6734ca7dd5eSAndreas Jaekel 		snprintf(buf, sizeof(buf),
674bfe96c74SAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", ZEV_TMPQUEUE_DEVICE_NAME);
675e9a5e479SAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
676e9a5e479SAndreas Jaekel 		if (q_fd < 0) {
677e9a5e479SAndreas Jaekel 			perror("opening queue device failed");
678e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
679e9a5e479SAndreas Jaekel 		}
6804ca7dd5eSAndreas Jaekel 	} else {
6814ca7dd5eSAndreas Jaekel 		q_fd = fd;
6824ca7dd5eSAndreas Jaekel 	}
683e9a5e479SAndreas Jaekel 
6842bb8e5e2SAndreas Jaekel 	while (1) {
685e9a5e479SAndreas Jaekel 		pfd[0].fd = q_fd;
6862bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
6872bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
6882bb8e5e2SAndreas Jaekel 		if (ret < 0) {
6892bb8e5e2SAndreas Jaekel 			perror("poll failed");
6904ca7dd5eSAndreas Jaekel 			close(q_fd);
691e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
6922bb8e5e2SAndreas Jaekel 		}
6932bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
6942bb8e5e2SAndreas Jaekel 			continue;
6952bb8e5e2SAndreas Jaekel 		/* data available */
696e9a5e479SAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
6972bb8e5e2SAndreas Jaekel 		if (ret < 0) {
6982bb8e5e2SAndreas Jaekel 			perror("read failed");
6994ca7dd5eSAndreas Jaekel 			close(q_fd);
700e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
7012bb8e5e2SAndreas Jaekel 		}
7022bb8e5e2SAndreas Jaekel 		if (ret == 0)
7032bb8e5e2SAndreas Jaekel 			continue;
70468a46c64SAndreas Jaekel 		while (ret > off) {
70568a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
70668a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
70768a46c64SAndreas Jaekel 			off += ev->header.record_len;
70868a46c64SAndreas Jaekel 		}
709108668daSAndreas Jaekel 		off = 0;
7102bb8e5e2SAndreas Jaekel 	}
7114ca7dd5eSAndreas Jaekel 	if (create_tmp_queue)
712e9a5e479SAndreas Jaekel 		close(q_fd);
713e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
7142bb8e5e2SAndreas Jaekel }
7152bb8e5e2SAndreas Jaekel 
716797b8adfSArne Jansen static int
717797b8adfSArne Jansen zev_dump_spool(int fd)
718797b8adfSArne Jansen {
719797b8adfSArne Jansen 	int len;
720797b8adfSArne Jansen 	char buf[4096];
721797b8adfSArne Jansen 	int off = 0;
722797b8adfSArne Jansen 
723797b8adfSArne Jansen 	while (1) {
724797b8adfSArne Jansen 		len = read(fd, buf + off, sizeof(buf) - off);
725797b8adfSArne Jansen 		if (len == -1) {
726797b8adfSArne Jansen 			fprintf(stderr, "reading from spool failed: %s\n",
727797b8adfSArne Jansen 				strerror(errno));
728797b8adfSArne Jansen 			return EXIT_FAILURE;
729797b8adfSArne Jansen 		}
730797b8adfSArne Jansen 		if (len == 0)
731797b8adfSArne Jansen 			break;
732797b8adfSArne Jansen 
733797b8adfSArne Jansen 		len += off;
734797b8adfSArne Jansen 		off = 0;
735797b8adfSArne Jansen 		while (len > off + sizeof(uint32_t)) {
736797b8adfSArne Jansen 			uint32_t evlen;
737797b8adfSArne Jansen 			char *mp;
738797b8adfSArne Jansen 			zev_event_t *ev;
739797b8adfSArne Jansen 
740797b8adfSArne Jansen 			ev = (zev_event_t *)(buf + off);
741797b8adfSArne Jansen 			evlen = ev->header.record_len;
742797b8adfSArne Jansen 			if (len < off + evlen + 1)
743797b8adfSArne Jansen 				break;
744797b8adfSArne Jansen 			mp = buf + off + evlen;
745797b8adfSArne Jansen 			if (!memchr(mp, 0, len - off - evlen))
746797b8adfSArne Jansen 				break;
747797b8adfSArne Jansen 			zev_print_event(buf + off, ev->header.record_len);
748797b8adfSArne Jansen 			off += ev->header.record_len + strlen(mp) + 1;
749797b8adfSArne Jansen 		}
750797b8adfSArne Jansen 
751797b8adfSArne Jansen 		memmove(buf, buf + off, len - off);
752797b8adfSArne Jansen 		off = len - off;
753797b8adfSArne Jansen 	}
754797b8adfSArne Jansen 
755797b8adfSArne Jansen 	return EXIT_SUCCESS;
756797b8adfSArne Jansen }
757797b8adfSArne Jansen 
7582bb8e5e2SAndreas Jaekel static void
7592bb8e5e2SAndreas Jaekel usage(char *progname)
7602bb8e5e2SAndreas Jaekel {
761e9a5e479SAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
762e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
763e9a5e479SAndreas Jaekel 	fprintf(stderr, " Status information:\n");
7642bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
7652bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
766797b8adfSArne Jansen 	fprintf(stderr, "   -f <name>            dump events from spool\n");
767e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
768e9a5e479SAndreas Jaekel 	        "information\n");
7690abdde4aSAndreas Jaekel 	fprintf(stderr, "   -T <interval> <cnt>  zevstat mode\n");
7709fd83c76SAndreas Jaekel 	fprintf(stderr, "   -R <base filename>   zevreport mode\n");
771e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
772e9a5e479SAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
773e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
774e9a5e479SAndreas Jaekel 	        "length\n");
775e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
776e9a5e479SAndreas Jaekel 	        "this pool\n");
7772bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
778e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
779e9a5e479SAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
780e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
7814ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
7824ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
783e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
784e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
785e9a5e479SAndreas Jaekel 	        "(default)\n");
786e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
787e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
7884ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
789e9a5e479SAndreas Jaekel 	        "length\n");
790e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
791e9a5e479SAndreas Jaekel 	        "throttle\n");
792e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
793e9a5e479SAndreas Jaekel 	fprintf(stderr, " Other options:\n");
794e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
795e9a5e479SAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
7964ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
7974ca7dd5eSAndreas Jaekel 		"queue name\n");
79801c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
799b9710123SAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
800b9710123SAndreas Jaekel 		"checksums\n");
801d65b2fffSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
8025e286361SAndreas Jaekel 	        "for some operations\n");
803d65b2fffSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
804d65b2fffSAndreas Jaekel 	        "one event per line\n");
805c62d8367SAndreas Jaekel 	fprintf(stderr, "   -V                   query zev module version\n");
806*c07f6d81SArne Jansen 	fprintf(stderr, "   -F                   flush output after each line\n");
8072bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
8082bb8e5e2SAndreas Jaekel }
8092bb8e5e2SAndreas Jaekel 
81029fab2f9SAndreas Jaekel static void
81129fab2f9SAndreas Jaekel zevstat_usage(char *progname)
81229fab2f9SAndreas Jaekel {
81329fab2f9SAndreas Jaekel 	fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname);
81429fab2f9SAndreas Jaekel 	fprintf(stderr, "   -v   verbose, show counters for all event types\n");
81529fab2f9SAndreas Jaekel 	exit (EXIT_FAILURE);
81629fab2f9SAndreas Jaekel }
81729fab2f9SAndreas Jaekel 
8189fd83c76SAndreas Jaekel static void
8199fd83c76SAndreas Jaekel zevreport_usage(char *progname)
8209fd83c76SAndreas Jaekel {
8219fd83c76SAndreas Jaekel 	fprintf(stderr, "usage: %s <output base filename>\n", progname);
8229fd83c76SAndreas Jaekel 	exit (EXIT_FAILURE);
8239fd83c76SAndreas Jaekel }
8249fd83c76SAndreas Jaekel 
8252bb8e5e2SAndreas Jaekel static int
8264ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
8272bb8e5e2SAndreas Jaekel {
828e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
829e9a5e479SAndreas Jaekel 	int namelen;
8302bb8e5e2SAndreas Jaekel 
831e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
832e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
833e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
8342bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
8352bb8e5e2SAndreas Jaekel 	}
836e9a5e479SAndreas Jaekel 
837e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
838e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
839b434d29cSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT | ZEV_FL_INITIALLY_EMPTY;
8404ca7dd5eSAndreas Jaekel 	if (blocking) {
8414ca7dd5eSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
8424ca7dd5eSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
8434ca7dd5eSAndreas Jaekel 	} else {
844e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
8454ca7dd5eSAndreas Jaekel 	}
846e9a5e479SAndreas Jaekel 
847e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
848e9a5e479SAndreas Jaekel 		perror("adding queue failed");
8492bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
8502bb8e5e2SAndreas Jaekel 	}
8512bb8e5e2SAndreas Jaekel 	return (0);
8522bb8e5e2SAndreas Jaekel }
8532bb8e5e2SAndreas Jaekel 
8542bb8e5e2SAndreas Jaekel static int
855e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg)
856205a9bc9SAndreas Jaekel {
857e9a5e479SAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
858e9a5e479SAndreas Jaekel 	int namelen;
859205a9bc9SAndreas Jaekel 
860e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
861e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
862e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
863205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
864205a9bc9SAndreas Jaekel 	}
865e9a5e479SAndreas Jaekel 
8664ca7dd5eSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
8674ca7dd5eSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
868e9a5e479SAndreas Jaekel 
869e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
870e9a5e479SAndreas Jaekel 		perror("removing queue failed");
871e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
872e9a5e479SAndreas Jaekel 	}
873e9a5e479SAndreas Jaekel 	return (0);
874e9a5e479SAndreas Jaekel }
875e9a5e479SAndreas Jaekel 
876e9a5e479SAndreas Jaekel static int
877e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
878e9a5e479SAndreas Jaekel {
879e9a5e479SAndreas Jaekel 	uint64_t maxqueuelen;
880e9a5e479SAndreas Jaekel 
881f36f5f13SAndreas Jaekel 	if (!arg) {
882f36f5f13SAndreas Jaekel 		fprintf(stderr, "missing queue length parameter\n");
883f36f5f13SAndreas Jaekel 		return (EXIT_FAILURE);
884f36f5f13SAndreas Jaekel 	}
885f36f5f13SAndreas Jaekel 
886e9a5e479SAndreas Jaekel 	errno = 0;
887e9a5e479SAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
888e9a5e479SAndreas Jaekel 	if (errno) {
889e9a5e479SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
890e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
891e9a5e479SAndreas Jaekel 	}
892e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
893e9a5e479SAndreas Jaekel 		perror("setting max queue length failed");
894205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
895205a9bc9SAndreas Jaekel 	}
896205a9bc9SAndreas Jaekel 	return (0);
897205a9bc9SAndreas Jaekel }
898205a9bc9SAndreas Jaekel 
899205a9bc9SAndreas Jaekel static int
9002bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
9012bb8e5e2SAndreas Jaekel {
9022bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
9032bb8e5e2SAndreas Jaekel 	int len;
9042bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
9052bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
9062bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
9072bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
9082bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
9092bb8e5e2SAndreas Jaekel 	}
9102bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
9112bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
9122bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
9132bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
9142bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
9152bb8e5e2SAndreas Jaekel 	}
9162bb8e5e2SAndreas Jaekel 	return (0);
9172bb8e5e2SAndreas Jaekel }
9182bb8e5e2SAndreas Jaekel 
9192bb8e5e2SAndreas Jaekel int
9202bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
9212bb8e5e2SAndreas Jaekel {
9222bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
9232bb8e5e2SAndreas Jaekel }
9242bb8e5e2SAndreas Jaekel 
9252bb8e5e2SAndreas Jaekel int
9262bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
9272bb8e5e2SAndreas Jaekel {
9282bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
9292bb8e5e2SAndreas Jaekel }
9302bb8e5e2SAndreas Jaekel 
93101c2c787SAndreas Jaekel static int
932e9a5e479SAndreas Jaekel zev_debug_info(int fd)
933e9a5e479SAndreas Jaekel {
934e9a5e479SAndreas Jaekel 	zev_ioctl_debug_info_t di;
935e9a5e479SAndreas Jaekel 
936e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
937e9a5e479SAndreas Jaekel 		perror("getting zev debug info failed");
938e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
939e9a5e479SAndreas Jaekel 	}
940e9a5e479SAndreas Jaekel 
941e9a5e479SAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
9425e286361SAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
9435e286361SAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
9445e286361SAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
945e9a5e479SAndreas Jaekel 	return 0;
946e9a5e479SAndreas Jaekel }
947e9a5e479SAndreas Jaekel 
948e9a5e479SAndreas Jaekel static int
94901c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
95001c2c787SAndreas Jaekel {
95101c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
95201c2c787SAndreas Jaekel 	uint64_t guid;
95301c2c787SAndreas Jaekel 	int len;
95401c2c787SAndreas Jaekel 	char *p;
95501c2c787SAndreas Jaekel 
95601c2c787SAndreas Jaekel 	p = strchr(arg, ':');
95701c2c787SAndreas Jaekel 	if (!p) {
95801c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
95901c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
96001c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
96101c2c787SAndreas Jaekel 	}
96201c2c787SAndreas Jaekel 	*p = '\n';
96301c2c787SAndreas Jaekel 	p++;
96401c2c787SAndreas Jaekel 
96501c2c787SAndreas Jaekel 	errno = 0;
966e9a5e479SAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
96701c2c787SAndreas Jaekel 	if (errno) {
96801c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
96901c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
97001c2c787SAndreas Jaekel 	}
97101c2c787SAndreas Jaekel 
97201c2c787SAndreas Jaekel 	len = strlen(p);
97301c2c787SAndreas Jaekel 
97401c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
97501c2c787SAndreas Jaekel 	if (!mark) {
97601c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
97701c2c787SAndreas Jaekel 		        strerror(errno));
97801c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
97901c2c787SAndreas Jaekel 	}
98001c2c787SAndreas Jaekel 	mark->zev_guid = guid;
98101c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
98201c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
98301c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
98401c2c787SAndreas Jaekel 
98501c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
98601c2c787SAndreas Jaekel 		perror("queueing mark failed");
98701c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
98801c2c787SAndreas Jaekel 	}
98901c2c787SAndreas Jaekel 
99001c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
99101c2c787SAndreas Jaekel 	return (0);
99201c2c787SAndreas Jaekel }
99301c2c787SAndreas Jaekel 
994e9a5e479SAndreas Jaekel static int
995e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
996e9a5e479SAndreas Jaekel {
997e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
998e9a5e479SAndreas Jaekel 
9994ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10004ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1001e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1002e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1003e9a5e479SAndreas Jaekel 	}
10044ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1005e9a5e479SAndreas Jaekel 
1006e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1007e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
1008e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1009e9a5e479SAndreas Jaekel 	}
1010e9a5e479SAndreas Jaekel 	if (block) {
1011e9a5e479SAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
1012e9a5e479SAndreas Jaekel 	} else {
1013e9a5e479SAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
1014e9a5e479SAndreas Jaekel 	}
1015e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1016e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
1017e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1018e9a5e479SAndreas Jaekel 	}
1019e9a5e479SAndreas Jaekel 	return (0);
1020e9a5e479SAndreas Jaekel }
1021e9a5e479SAndreas Jaekel 
1022e9a5e479SAndreas Jaekel static int
1023e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
1024e9a5e479SAndreas Jaekel {
1025e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1026e9a5e479SAndreas Jaekel 
1027e9a5e479SAndreas Jaekel 	if (!len) {
1028e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
1029e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1030e9a5e479SAndreas Jaekel 	}
1031e9a5e479SAndreas Jaekel 
10324ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10334ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1034e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1035e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1036e9a5e479SAndreas Jaekel 	}
10374ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1038e9a5e479SAndreas Jaekel 
1039e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1040e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
1041e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1042e9a5e479SAndreas Jaekel 	}
1043e9a5e479SAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
1044e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
1045e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
1046e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1047e9a5e479SAndreas Jaekel 	}
1048e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
1049e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
1050e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1051e9a5e479SAndreas Jaekel 	}
1052e9a5e479SAndreas Jaekel 
1053e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1054e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
1055e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1056e9a5e479SAndreas Jaekel 	}
1057e9a5e479SAndreas Jaekel 	return (0);
1058e9a5e479SAndreas Jaekel }
1059e9a5e479SAndreas Jaekel 
1060e9a5e479SAndreas Jaekel static int
1061e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
1062e9a5e479SAndreas Jaekel {
1063e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1064e9a5e479SAndreas Jaekel 
1065e9a5e479SAndreas Jaekel 	if (!len) {
1066e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
1067e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1068e9a5e479SAndreas Jaekel 	}
1069e9a5e479SAndreas Jaekel 
10704ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10714ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1072e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1073e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1074e9a5e479SAndreas Jaekel 	}
10754ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1076e9a5e479SAndreas Jaekel 
1077e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1078e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
1079e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1080e9a5e479SAndreas Jaekel 	}
1081e9a5e479SAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
1082e9a5e479SAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
1083e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
1084e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1085e9a5e479SAndreas Jaekel 	}
10864ca7dd5eSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
1087e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
1088e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1089e9a5e479SAndreas Jaekel 	}
1090e9a5e479SAndreas Jaekel 
1091e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1092e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
1093e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1094e9a5e479SAndreas Jaekel 	}
1095e9a5e479SAndreas Jaekel 	return (0);
1096e9a5e479SAndreas Jaekel }
1097e9a5e479SAndreas Jaekel 
1098e9a5e479SAndreas Jaekel static int
1099e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg)
1100e9a5e479SAndreas Jaekel {
1101e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1102e9a5e479SAndreas Jaekel 
11034ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
11044ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1105e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1106e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
1107e9a5e479SAndreas Jaekel 	}
11084ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1109e9a5e479SAndreas Jaekel 
1110e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1111e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
1112e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1113e9a5e479SAndreas Jaekel 	}
1114e9a5e479SAndreas Jaekel 
1115e9a5e479SAndreas Jaekel 	printf("queue        : %s\n", arg);
1116e9a5e479SAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1117e9a5e479SAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1118e9a5e479SAndreas Jaekel 	printf("persistent   : %s\n",
1119e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1120e9a5e479SAndreas Jaekel 	printf("blocking     : %s\n",
1121e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1122e9a5e479SAndreas Jaekel 
1123e9a5e479SAndreas Jaekel 	return (0);
1124e9a5e479SAndreas Jaekel }
1125e9a5e479SAndreas Jaekel 
1126e9a5e479SAndreas Jaekel static int
1127e9a5e479SAndreas Jaekel zev_list_queues(int fd)
1128e9a5e479SAndreas Jaekel {
1129e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1130e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1131e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1132e9a5e479SAndreas Jaekel 	uint64_t	i;
1133e9a5e479SAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1134662d8e03SAndreas Jaekel 	zev_statistics_t zs;
1135662d8e03SAndreas Jaekel 
1136662d8e03SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
1137662d8e03SAndreas Jaekel 		perror("getting statistics data failed");
1138662d8e03SAndreas Jaekel 		return (EXIT_FAILURE);
1139662d8e03SAndreas Jaekel 	}
1140e9a5e479SAndreas Jaekel 
1141e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1142e9a5e479SAndreas Jaekel 		perror("getting queue list failed");
1143e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
1144e9a5e479SAndreas Jaekel 	}
1145e9a5e479SAndreas Jaekel 
1146e9a5e479SAndreas Jaekel 	printf("Name                                     Size       "
1147662d8e03SAndreas Jaekel 	       "Size%% Max Size   Per Block\n");
1148e9a5e479SAndreas Jaekel 
1149e9a5e479SAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1150e9a5e479SAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1151e9a5e479SAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1152e9a5e479SAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1153e9a5e479SAndreas Jaekel 
11544ca7dd5eSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
11554ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11564ca7dd5eSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
11574ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1158e9a5e479SAndreas Jaekel 
1159e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1160e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
1161e9a5e479SAndreas Jaekel 				continue;
1162e9a5e479SAndreas Jaekel 			perror("getting queue properties failed");
1163e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
1164e9a5e479SAndreas Jaekel 		}
1165e9a5e479SAndreas Jaekel 
11664ca7dd5eSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
11674ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11684ca7dd5eSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
11694ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1170e9a5e479SAndreas Jaekel 
1171e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1172e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
1173e9a5e479SAndreas Jaekel 				continue;
1174e9a5e479SAndreas Jaekel 			perror("getting statistics data failed");
1175e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
1176e9a5e479SAndreas Jaekel 		}
1177e9a5e479SAndreas Jaekel 
1178662d8e03SAndreas Jaekel 		if (gqp.zev_max_queue_len == 0) {
1179662d8e03SAndreas Jaekel 			gqp.zev_max_queue_len = zs.zev_max_queue_len;
1180662d8e03SAndreas Jaekel 		}
1181662d8e03SAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %5.1f %-10" PRIu64
1182e9a5e479SAndreas Jaekel 		       " %-3s %-3s\n",
1183e9a5e479SAndreas Jaekel 			name,
1184662d8e03SAndreas Jaekel 			gs.zev_statistics.zev_queue_len * 100.0 /
1185662d8e03SAndreas Jaekel 				gqp.zev_max_queue_len,
1186e9a5e479SAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1187e9a5e479SAndreas Jaekel 			gqp.zev_max_queue_len,
1188e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1189e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1190e9a5e479SAndreas Jaekel 				 "yes" : "no");
1191e9a5e479SAndreas Jaekel 	}
1192e9a5e479SAndreas Jaekel 
1193e9a5e479SAndreas Jaekel 	return (0);
1194e9a5e479SAndreas Jaekel }
1195e9a5e479SAndreas Jaekel 
1196b9710123SAndreas Jaekel static int
1197b9710123SAndreas Jaekel zev_checksum(int dev_fd, char *filename)
1198b9710123SAndreas Jaekel {
1199b9710123SAndreas Jaekel 	int fd;
1200b9710123SAndreas Jaekel 	offset_t off;
1201b9710123SAndreas Jaekel 	offset_t data;
1202b9710123SAndreas Jaekel 	zev_sig_t *sig;
1203b9710123SAndreas Jaekel 	char *buf;
1204b9710123SAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
1205b9710123SAndreas Jaekel 	int i;
1206b9710123SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
1207b9710123SAndreas Jaekel 	int buf_size;
1208b9710123SAndreas Jaekel 
1209b9710123SAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
1210b9710123SAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
1211b9710123SAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
1212b9710123SAndreas Jaekel 	if (!buf) {
1213b9710123SAndreas Jaekel 		perror("can't allocate checksum buffer");
1214b9710123SAndreas Jaekel 		return (EXIT_FAILURE);
1215b9710123SAndreas Jaekel 	}
1216b9710123SAndreas Jaekel 
1217b9710123SAndreas Jaekel 	fd = open(filename, O_RDONLY);
1218b9710123SAndreas Jaekel 	if (fd < 0) {
1219b9710123SAndreas Jaekel 		perror("can't open file");
1220b9710123SAndreas Jaekel 		return (EXIT_FAILURE);
1221b9710123SAndreas Jaekel 	}
1222b9710123SAndreas Jaekel 
1223b9710123SAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
1224b9710123SAndreas Jaekel 	gs->zev_fd = fd;
1225b9710123SAndreas Jaekel 	gs->zev_bufsize = buf_size;
1226b9710123SAndreas Jaekel 
1227b9710123SAndreas Jaekel 	off = 0;
1228b9710123SAndreas Jaekel 	data = 0;
1229b9710123SAndreas Jaekel 	while (1) {
1230b9710123SAndreas Jaekel 		errno = 0;
1231b9710123SAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
1232b9710123SAndreas Jaekel 		if (data < 0) {
1233b9710123SAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
1234b9710123SAndreas Jaekel 				break;
1235b9710123SAndreas Jaekel 			perror("llseek failed");
1236b9710123SAndreas Jaekel 			goto err;
1237b9710123SAndreas Jaekel 		}
1238b9710123SAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
1239b9710123SAndreas Jaekel 		off = data + ZEV_L1_SIZE;
1240b9710123SAndreas Jaekel 
1241b9710123SAndreas Jaekel 		gs->zev_offset = data;
1242b9710123SAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
1243b9710123SAndreas Jaekel 
1244b9710123SAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
1245b9710123SAndreas Jaekel 			perror("ioctl to get signatures failed");
1246b9710123SAndreas Jaekel 			goto err;
1247b9710123SAndreas Jaekel 		}
1248b9710123SAndreas Jaekel 
1249b9710123SAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
1250b9710123SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
1251b9710123SAndreas Jaekel 			sig += i;
1252b9710123SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
1253b9710123SAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
1254b9710123SAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
1255b9710123SAndreas Jaekel 		}
1256b9710123SAndreas Jaekel 	}
1257b9710123SAndreas Jaekel 
1258b9710123SAndreas Jaekel 	free(buf);
1259b9710123SAndreas Jaekel 	close(fd);
1260b9710123SAndreas Jaekel 	return 0;
1261b9710123SAndreas Jaekel err:
1262b9710123SAndreas Jaekel 	free(buf);
1263b9710123SAndreas Jaekel 	close(fd);
1264b9710123SAndreas Jaekel 	return (EXIT_FAILURE);
1265b9710123SAndreas Jaekel }
1266b9710123SAndreas Jaekel 
12670abdde4aSAndreas Jaekel typedef struct zevstat {
12680abdde4aSAndreas Jaekel 	uint64_t	ns_start;
12690abdde4aSAndreas Jaekel 	uint64_t	events[ZEV_OP_MIN + ZEV_OP_MAX];
12700abdde4aSAndreas Jaekel 	uint64_t	guids;
12710abdde4aSAndreas Jaekel 	uint64_t	total_events;
12720abdde4aSAndreas Jaekel 	uint64_t	total_guids;
12730abdde4aSAndreas Jaekel 	avl_tree_t	guids_interval;
12740abdde4aSAndreas Jaekel 	avl_tree_t	guids_runtime;
12750abdde4aSAndreas Jaekel } zevstat_t;
12760abdde4aSAndreas Jaekel 
12770abdde4aSAndreas Jaekel typedef struct zev_guidtrack_t {
12780abdde4aSAndreas Jaekel 	uint64_t	guid;
12790abdde4aSAndreas Jaekel 	avl_node_t	avl_interval;
12800abdde4aSAndreas Jaekel 	avl_node_t	avl_runtime;
12810abdde4aSAndreas Jaekel } zev_guidtrack_t;
12820abdde4aSAndreas Jaekel 
12830abdde4aSAndreas Jaekel zevstat_t zevstat;
12840abdde4aSAndreas Jaekel 
12850abdde4aSAndreas Jaekel static void
12860abdde4aSAndreas Jaekel zev_eventstat(char *buf, int len)
12870abdde4aSAndreas Jaekel {
12880abdde4aSAndreas Jaekel 	zev_header_t *rec = (zev_header_t *)buf;
12890abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt;
12900abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt_int;
12910abdde4aSAndreas Jaekel 	zev_guidtrack_t to_find;
12920abdde4aSAndreas Jaekel 	avl_index_t where;
12930abdde4aSAndreas Jaekel 
12940abdde4aSAndreas Jaekel 	zevstat.total_events++;
12950abdde4aSAndreas Jaekel 	zevstat.events[rec->op]++;
12960abdde4aSAndreas Jaekel 
12970abdde4aSAndreas Jaekel 	to_find.guid = rec->guid;
12980abdde4aSAndreas Jaekel 	gt = avl_find(&zevstat.guids_runtime, &to_find, &where);
12990abdde4aSAndreas Jaekel 	if (!gt) {
13000abdde4aSAndreas Jaekel 		gt = malloc(sizeof(*gt));
13010abdde4aSAndreas Jaekel 		if (!gt) {
13020abdde4aSAndreas Jaekel 			perror("can't get guid tracking record");
13030abdde4aSAndreas Jaekel 			exit (EXIT_FAILURE);
13040abdde4aSAndreas Jaekel 		}
13050abdde4aSAndreas Jaekel 		gt->guid = rec->guid;
13060abdde4aSAndreas Jaekel 		avl_insert(&zevstat.guids_runtime, gt, where);
13070abdde4aSAndreas Jaekel 	}
13080abdde4aSAndreas Jaekel 	gt_int = avl_find(&zevstat.guids_interval, &to_find, &where);
13090abdde4aSAndreas Jaekel 	if (!gt_int)
13100abdde4aSAndreas Jaekel 		avl_insert(&zevstat.guids_interval, gt, where);
13110abdde4aSAndreas Jaekel }
13120abdde4aSAndreas Jaekel 
13130abdde4aSAndreas Jaekel static void
13149fd83c76SAndreas Jaekel zev_eventstat_interval(FILE *out)
13150abdde4aSAndreas Jaekel {
13160abdde4aSAndreas Jaekel 	uint64_t events;
13170abdde4aSAndreas Jaekel 	int i;
13180abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt;
13190abdde4aSAndreas Jaekel 
13200abdde4aSAndreas Jaekel 	events = 0;
13210abdde4aSAndreas Jaekel 	for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) {
13220abdde4aSAndreas Jaekel 		events += zevstat.events[i];
13230abdde4aSAndreas Jaekel 	}
13240abdde4aSAndreas Jaekel 
13250abdde4aSAndreas Jaekel 	if (verbose) {
13269fd83c76SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu  ",
13270abdde4aSAndreas Jaekel 		        time(NULL),
13280abdde4aSAndreas Jaekel 		        events,
13290abdde4aSAndreas Jaekel 		        zevstat.total_events,
13300abdde4aSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
13310abdde4aSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
13320abdde4aSAndreas Jaekel 		for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++)
13339fd83c76SAndreas Jaekel 			fprintf(out, "%6llu ", zevstat.events[i]);
13349fd83c76SAndreas Jaekel 		fprintf(out, "\n");
13350abdde4aSAndreas Jaekel 	} else {
13369fd83c76SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu\n",
13370abdde4aSAndreas Jaekel 		        time(NULL),
13380abdde4aSAndreas Jaekel 		        events,
13390abdde4aSAndreas Jaekel 		        zevstat.total_events,
13400abdde4aSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
13410abdde4aSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
13420abdde4aSAndreas Jaekel 	}
13430abdde4aSAndreas Jaekel 	memset(&zevstat.events, 0, sizeof(zevstat.events));
13440abdde4aSAndreas Jaekel 	zevstat.guids = 0;
13450abdde4aSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
13460abdde4aSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
13479fd83c76SAndreas Jaekel 	fflush(out);
13480abdde4aSAndreas Jaekel }
13490abdde4aSAndreas Jaekel 
13500abdde4aSAndreas Jaekel static int
13510abdde4aSAndreas Jaekel zev_evcompar(const void *a, const void *b)
13520abdde4aSAndreas Jaekel {
13530abdde4aSAndreas Jaekel 	const zev_guidtrack_t *ga = a;
13540abdde4aSAndreas Jaekel 	const zev_guidtrack_t *gb = b;
13550abdde4aSAndreas Jaekel 
13560abdde4aSAndreas Jaekel 	if (ga->guid > gb->guid)
13570abdde4aSAndreas Jaekel 		return 1;
13580abdde4aSAndreas Jaekel 	if (ga->guid < gb->guid)
13590abdde4aSAndreas Jaekel 		return -1;
13600abdde4aSAndreas Jaekel 	return 0;
13610abdde4aSAndreas Jaekel }
13620abdde4aSAndreas Jaekel 
13630abdde4aSAndreas Jaekel static int
13649fd83c76SAndreas Jaekel zev_zevstat(int fd, char *s_interval, char *s_count, char *outfile)
13650abdde4aSAndreas Jaekel {
13660abdde4aSAndreas Jaekel 	uint64_t interval = 1000;
13670abdde4aSAndreas Jaekel 	uint64_t ms;
13680abdde4aSAndreas Jaekel 	uint64_t t_until;
13690abdde4aSAndreas Jaekel 	uint64_t t_now;
13700abdde4aSAndreas Jaekel 	int cnt = -1;
13710abdde4aSAndreas Jaekel 	struct pollfd pfd[1];
13720abdde4aSAndreas Jaekel 	int ret;
13730abdde4aSAndreas Jaekel 	char buf[4096];
13740abdde4aSAndreas Jaekel 	zev_event_t *ev;
13750abdde4aSAndreas Jaekel 	int off = 0;
13760abdde4aSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
13770abdde4aSAndreas Jaekel 	int q_fd;
13780abdde4aSAndreas Jaekel 	zev_guidtrack_t *gt;
13799fd83c76SAndreas Jaekel 	FILE *out = stdout;
13809fd83c76SAndreas Jaekel 	struct stat st;
13819fd83c76SAndreas Jaekel 	char filename[MAXPATHLEN];
13829fd83c76SAndreas Jaekel 	int retry;
13839fd83c76SAndreas Jaekel 
13849fd83c76SAndreas Jaekel 	if (outfile) {
13859fd83c76SAndreas Jaekel 		retry = 0;
13869fd83c76SAndreas Jaekel 		strncpy(filename, outfile, sizeof(filename));
13879fd83c76SAndreas Jaekel 		while (stat(filename, &st) == 0) {
13889fd83c76SAndreas Jaekel 			/* file exists */
13899fd83c76SAndreas Jaekel 			snprintf(filename, sizeof(filename),
13909fd83c76SAndreas Jaekel 			         "%s.%d", outfile, retry);
13919fd83c76SAndreas Jaekel 			retry++;
13929fd83c76SAndreas Jaekel 		}
13939fd83c76SAndreas Jaekel 		out = fopen(filename, "wb+");
13949fd83c76SAndreas Jaekel 		if (!out) {
13959fd83c76SAndreas Jaekel 			perror("opening output file failed");
13969fd83c76SAndreas Jaekel 			return (EXIT_FAILURE);
13979fd83c76SAndreas Jaekel 		}
13989fd83c76SAndreas Jaekel 	}
13990abdde4aSAndreas Jaekel 
14000abdde4aSAndreas Jaekel 	memset(&zevstat, 0, sizeof(zevstat));
14010abdde4aSAndreas Jaekel 	avl_create(&zevstat.guids_runtime, zev_evcompar,
14020abdde4aSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
14030abdde4aSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_runtime));
14040abdde4aSAndreas Jaekel 	avl_create(&zevstat.guids_interval, zev_evcompar,
14050abdde4aSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
14060abdde4aSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_interval));
14070abdde4aSAndreas Jaekel 
1408ddaa5fcfSAndreas Jaekel 	if (s_interval) {
14090abdde4aSAndreas Jaekel 		interval = atol(s_interval);
14100abdde4aSAndreas Jaekel 		if (interval == 0) {
14110abdde4aSAndreas Jaekel 			fprintf(stderr, "invalid interval.\n");
14120abdde4aSAndreas Jaekel 			return (EXIT_FAILURE);
14130abdde4aSAndreas Jaekel 		}
14140abdde4aSAndreas Jaekel 		interval *= 1000;
1415ddaa5fcfSAndreas Jaekel 	}
14160abdde4aSAndreas Jaekel 	if (s_count) {
14170abdde4aSAndreas Jaekel 		cnt = atol(s_count);
14180abdde4aSAndreas Jaekel 		if (interval == 0) {
14190abdde4aSAndreas Jaekel 			fprintf(stderr, "invalid count.\n");
14200abdde4aSAndreas Jaekel 			return (EXIT_FAILURE);
14210abdde4aSAndreas Jaekel 		}
14220abdde4aSAndreas Jaekel 	}
14230abdde4aSAndreas Jaekel 
14240abdde4aSAndreas Jaekel 	aq.zev_max_queue_len = 1024 * 1024;
1425b434d29cSAndreas Jaekel 	aq.zev_flags = ZEV_FL_INITIALLY_EMPTY;
14260abdde4aSAndreas Jaekel 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
14270abdde4aSAndreas Jaekel 		 "zevstat.%ld.%ld", time(NULL), getpid());
14280abdde4aSAndreas Jaekel 	aq.zev_namelen = strlen(aq.zev_name);
14290abdde4aSAndreas Jaekel 
14300abdde4aSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
14310abdde4aSAndreas Jaekel 		perror("adding temporary queue failed");
14320abdde4aSAndreas Jaekel 		return (EXIT_FAILURE);
14330abdde4aSAndreas Jaekel 	}
14340abdde4aSAndreas Jaekel 
14350abdde4aSAndreas Jaekel 	snprintf(buf, sizeof(buf),
14360abdde4aSAndreas Jaekel 		 "/devices/pseudo/zev@0:%s", aq.zev_name);
14370abdde4aSAndreas Jaekel 	q_fd = open(buf, O_RDONLY);
14380abdde4aSAndreas Jaekel 	if (q_fd < 0) {
14390abdde4aSAndreas Jaekel 		perror("opening queue device failed");
14400abdde4aSAndreas Jaekel 		return (EXIT_FAILURE);
14410abdde4aSAndreas Jaekel 	}
14420abdde4aSAndreas Jaekel 
14430abdde4aSAndreas Jaekel 	pfd[0].fd = q_fd;
14440abdde4aSAndreas Jaekel 	pfd[0].events = POLLIN;
14450abdde4aSAndreas Jaekel 
14460abdde4aSAndreas Jaekel 	/* drain queue */
1447ddaa5fcfSAndreas Jaekel 	while ((ret = poll(pfd, 1, 0)) > 0) {
14480abdde4aSAndreas Jaekel 		if (read(q_fd, buf, sizeof(buf)) < 0) {
14490abdde4aSAndreas Jaekel 			perror("read failed");
14500abdde4aSAndreas Jaekel 			close(q_fd);
14510abdde4aSAndreas Jaekel 			return(EXIT_FAILURE);
14520abdde4aSAndreas Jaekel 		}
14530abdde4aSAndreas Jaekel 	}
14540abdde4aSAndreas Jaekel 	if (ret < 0) {
14550abdde4aSAndreas Jaekel 		perror("poll failed");
14560abdde4aSAndreas Jaekel 		close(q_fd);
14570abdde4aSAndreas Jaekel 		return(EXIT_FAILURE);
14580abdde4aSAndreas Jaekel 	}
14590abdde4aSAndreas Jaekel 
14609fd83c76SAndreas Jaekel 	fprintf(out, "timestamp   events tevents  guids tguids");
14610abdde4aSAndreas Jaekel 	if (verbose) {
14629fd83c76SAndreas Jaekel 		fprintf(out, "   error   mark  mount umount zvol_w ");
14639fd83c76SAndreas Jaekel 		fprintf(out, "zvol_t  close create  mkdir mxattr ");
14649fd83c76SAndreas Jaekel 		fprintf(out, "remove  rmdir   link symlnk rename  ");
14659fd83c76SAndreas Jaekel 		fprintf(out, "write  trunc setatt    acl");
14660abdde4aSAndreas Jaekel 	}
14679fd83c76SAndreas Jaekel 	fprintf(out, "\n");
14680abdde4aSAndreas Jaekel 	while (cnt) {
14690abdde4aSAndreas Jaekel 		t_until = gethrtime() + (interval * 1000000);
14700abdde4aSAndreas Jaekel 		ms = interval;
14710abdde4aSAndreas Jaekel 		do {
14720abdde4aSAndreas Jaekel 			ret = poll(pfd, 1, ms);
14730abdde4aSAndreas Jaekel 			t_now = gethrtime();
14740abdde4aSAndreas Jaekel 			if (t_now < t_until) {
14750abdde4aSAndreas Jaekel 				ms = t_until - t_now;
14760abdde4aSAndreas Jaekel 				ms /= 1000000ull;
14770abdde4aSAndreas Jaekel 			}
14780abdde4aSAndreas Jaekel 			if (ret < 0) {
14790abdde4aSAndreas Jaekel 				perror("poll failed");
14800abdde4aSAndreas Jaekel 				close(q_fd);
14810abdde4aSAndreas Jaekel 				return(EXIT_FAILURE);
14820abdde4aSAndreas Jaekel 			}
14830abdde4aSAndreas Jaekel 			if (!(pfd[0].revents & POLLIN))
14840abdde4aSAndreas Jaekel 				continue;
14850abdde4aSAndreas Jaekel 			/* data available */
14860abdde4aSAndreas Jaekel 			ret = read(q_fd, buf, sizeof(buf));
14870abdde4aSAndreas Jaekel 			if (ret < 0) {
14880abdde4aSAndreas Jaekel 				perror("read failed");
14890abdde4aSAndreas Jaekel 				close(q_fd);
14900abdde4aSAndreas Jaekel 				return(EXIT_FAILURE);
14910abdde4aSAndreas Jaekel 			}
14920abdde4aSAndreas Jaekel 			if (ret == 0)
14930abdde4aSAndreas Jaekel 				continue;
14940abdde4aSAndreas Jaekel 			while (ret > off) {
14950abdde4aSAndreas Jaekel 				ev = (zev_event_t *)(buf + off);
14960abdde4aSAndreas Jaekel 				zev_eventstat(buf + off, ev->header.record_len);
14970abdde4aSAndreas Jaekel 				off += ev->header.record_len;
14980abdde4aSAndreas Jaekel 			}
14990abdde4aSAndreas Jaekel 			off = 0;
15000abdde4aSAndreas Jaekel 		} while ((t_now) < t_until && (ms > 0));
15019fd83c76SAndreas Jaekel 		zev_eventstat_interval(out);
15020abdde4aSAndreas Jaekel 		if (cnt > 0)
15030abdde4aSAndreas Jaekel 			cnt--;
15040abdde4aSAndreas Jaekel 	}
15050abdde4aSAndreas Jaekel 	close(q_fd);
15069fd83c76SAndreas Jaekel 	if (outfile)
15079fd83c76SAndreas Jaekel 		fclose(out);
15080abdde4aSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
15090abdde4aSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
15100abdde4aSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_runtime)) {
15110abdde4aSAndreas Jaekel 		avl_remove(&zevstat.guids_runtime, gt);
15120abdde4aSAndreas Jaekel 		free(gt);
15130abdde4aSAndreas Jaekel 	}
15140abdde4aSAndreas Jaekel 	return EXIT_SUCCESS;
15150abdde4aSAndreas Jaekel }
15160abdde4aSAndreas Jaekel 
15179fd83c76SAndreas Jaekel static int
15189fd83c76SAndreas Jaekel zev_report(int fd, char *basename)
15199fd83c76SAndreas Jaekel {
15209fd83c76SAndreas Jaekel 	char filename[MAXPATHLEN];
15219fd83c76SAndreas Jaekel 	char count[10];
15229fd83c76SAndreas Jaekel 	time_t now;
15239fd83c76SAndreas Jaekel 	time_t midnight;
15249fd83c76SAndreas Jaekel 	struct tm tm;
15259fd83c76SAndreas Jaekel 	int minutes;
15269fd83c76SAndreas Jaekel 	int ret;
15279fd83c76SAndreas Jaekel 
15289fd83c76SAndreas Jaekel 	verbose++;
15299fd83c76SAndreas Jaekel 	while (1) {
15309fd83c76SAndreas Jaekel 		now = time(NULL);
15319fd83c76SAndreas Jaekel 		localtime_r(&now, &tm);
15329fd83c76SAndreas Jaekel 		snprintf(filename, sizeof(filename), "%s.%04d-%02d-%02d",
15339fd83c76SAndreas Jaekel 		         basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
15349fd83c76SAndreas Jaekel 		tm.tm_sec = 0;
15359fd83c76SAndreas Jaekel 		tm.tm_min = 0;
15369fd83c76SAndreas Jaekel 		tm.tm_hour = 0;
15379fd83c76SAndreas Jaekel 		tm.tm_mday++;  /* works for Jan 32nd, Feb 30th, etc. */
15389fd83c76SAndreas Jaekel 		midnight = mktime(&tm);
15399fd83c76SAndreas Jaekel 		if (now % 60)
15409fd83c76SAndreas Jaekel 			sleep(60 - (now % 60));
15419fd83c76SAndreas Jaekel 		minutes = (midnight - time(NULL)) / 60;
15429fd83c76SAndreas Jaekel 		snprintf(count, sizeof(count), "%d", minutes);
15439fd83c76SAndreas Jaekel 		ret = zev_zevstat(fd, "60", count, filename);
15449fd83c76SAndreas Jaekel 		if (ret)
15459fd83c76SAndreas Jaekel 			return EXIT_FAILURE;
15469fd83c76SAndreas Jaekel 	}
15479fd83c76SAndreas Jaekel 	return EXIT_SUCCESS; /* never reached */
15489fd83c76SAndreas Jaekel }
15499fd83c76SAndreas Jaekel 
1550c62d8367SAndreas Jaekel static int
1551c62d8367SAndreas Jaekel zev_get_zev_version(int fd)
1552c62d8367SAndreas Jaekel {
1553c62d8367SAndreas Jaekel 	zev_ioctl_get_zev_version vi;
1554c62d8367SAndreas Jaekel 
1555c62d8367SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_ZEV_VERSION, &vi)) {
1556c62d8367SAndreas Jaekel 		perror("getting zev cersion info failed");
1557c62d8367SAndreas Jaekel 		return (EXIT_FAILURE);
1558c62d8367SAndreas Jaekel 	}
1559c62d8367SAndreas Jaekel 
1560c62d8367SAndreas Jaekel 	printf("zev major version: %llu\n", vi.zev_major_version);
1561c62d8367SAndreas Jaekel 	printf("zev minor version: %llu\n", vi.zev_minor_version);
1562c62d8367SAndreas Jaekel 	return 0;
1563c62d8367SAndreas Jaekel }
1564c62d8367SAndreas Jaekel 
1565c69e8453SAndreas Jaekel static void
1566c69e8453SAndreas Jaekel zev_sigint(int sig)
1567c69e8453SAndreas Jaekel {
1568c69e8453SAndreas Jaekel 	fflush(stdout);
1569c69e8453SAndreas Jaekel }
1570c69e8453SAndreas Jaekel 
15712bb8e5e2SAndreas Jaekel int
15722bb8e5e2SAndreas Jaekel main(int argc, char **argv)
15732bb8e5e2SAndreas Jaekel {
15742bb8e5e2SAndreas Jaekel 	int fd;
15752bb8e5e2SAndreas Jaekel 	int c;
15762bb8e5e2SAndreas Jaekel 	extern char *optarg;
15774ca7dd5eSAndreas Jaekel 	int create_tmp_queue = 1;
15784ca7dd5eSAndreas Jaekel 	char buf[MAXPATHLEN];
15796a3d43bfSAndreas Jaekel 	int mode = 0;
15806a3d43bfSAndreas Jaekel 	char *arg = NULL;
15816a3d43bfSAndreas Jaekel 	char *arg2 = NULL;
15820abdde4aSAndreas Jaekel 	char *p;
15830abdde4aSAndreas Jaekel 
1584c69e8453SAndreas Jaekel 	sigset(SIGINT, zev_sigint);
1585c69e8453SAndreas Jaekel 
158629fab2f9SAndreas Jaekel 	/* open device */
158729fab2f9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
158829fab2f9SAndreas Jaekel 	if (fd < 0) {
158929fab2f9SAndreas Jaekel 		perror("opening zev device failed");
159029fab2f9SAndreas Jaekel 		return EXIT_FAILURE;
159129fab2f9SAndreas Jaekel 	}
159229fab2f9SAndreas Jaekel 
15930abdde4aSAndreas Jaekel 	p = strrchr(argv[0], '/');
15940abdde4aSAndreas Jaekel 	if (!p) {
15950abdde4aSAndreas Jaekel 		p = argv[0];
15960abdde4aSAndreas Jaekel 	} else {
15970abdde4aSAndreas Jaekel 		p++;
15980abdde4aSAndreas Jaekel 	}
15990abdde4aSAndreas Jaekel 	if (!strcmp(p, "zevstat")) {
16000abdde4aSAndreas Jaekel 		mode = MD_ZEVSTAT;
160129fab2f9SAndreas Jaekel 		if (argc < 2)
160229fab2f9SAndreas Jaekel 			zevstat_usage(argv[0]);
160329fab2f9SAndreas Jaekel 		if (!strcmp(argv[1], "-v")) {
160429fab2f9SAndreas Jaekel 			if (argc < 3)
160529fab2f9SAndreas Jaekel 				zevstat_usage(argv[0]);
160629fab2f9SAndreas Jaekel 			verbose++;
160729fab2f9SAndreas Jaekel 			arg = argv[2];
160829fab2f9SAndreas Jaekel 			arg2 = argv[3];
160929fab2f9SAndreas Jaekel 		} else {
161029fab2f9SAndreas Jaekel 			arg = argv[1];
161129fab2f9SAndreas Jaekel 			arg2 = argv[2];
161229fab2f9SAndreas Jaekel 		}
16139fd83c76SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
16149fd83c76SAndreas Jaekel 	} else if(!strcmp(p, "zevreport")) {
16159fd83c76SAndreas Jaekel 		mode = MD_ZEV_REPORT;
16169fd83c76SAndreas Jaekel 		if (argc != 2)
16179fd83c76SAndreas Jaekel 			zevreport_usage(argv[0]);
16189fd83c76SAndreas Jaekel 		return zev_report(fd, argv[1]);
16190abdde4aSAndreas Jaekel 	}
16202bb8e5e2SAndreas Jaekel 
16214ca7dd5eSAndreas Jaekel 	while ((c = getopt(argc, argv,
1622*c07f6d81SArne Jansen 	   "a:A:b:B:c:d:Df:Fghk:lL:m:M:pP:q:Q:r:R:st:T:vV?")) != -1) {
16232bb8e5e2SAndreas Jaekel 		switch(c) {
1624d65b2fffSAndreas Jaekel 		case 'g':
1625d65b2fffSAndreas Jaekel 			grep_friendly++;
1626d65b2fffSAndreas Jaekel 			verbose++;
1627d65b2fffSAndreas Jaekel 			break;
16285e286361SAndreas Jaekel 		case 'v':
16295e286361SAndreas Jaekel 			verbose++;
16305e286361SAndreas Jaekel 			break;
16312bb8e5e2SAndreas Jaekel 		case 's':
16326a3d43bfSAndreas Jaekel 			mode = MD_STATISTICS;
16336a3d43bfSAndreas Jaekel 			break;
16342bb8e5e2SAndreas Jaekel 		case 'p':
16356a3d43bfSAndreas Jaekel 			mode = MD_POLL_EVENTS;
16366a3d43bfSAndreas Jaekel 			break;
1637b9710123SAndreas Jaekel 		case 'c':
16386a3d43bfSAndreas Jaekel 			mode = MD_CHECKSUMS;
16396a3d43bfSAndreas Jaekel 			arg = optarg;
16406a3d43bfSAndreas Jaekel 			break;
1641e9a5e479SAndreas Jaekel 		case 'D':
16426a3d43bfSAndreas Jaekel 			mode = MD_DEBUG_INFO;
16436a3d43bfSAndreas Jaekel 			break;
16442bb8e5e2SAndreas Jaekel 		case 'd':
1645e9a5e479SAndreas Jaekel 			close(fd);
16462bb8e5e2SAndreas Jaekel 			zev_device = optarg;
1647e9a5e479SAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1648e9a5e479SAndreas Jaekel 			if (fd < 0) {
1649e9a5e479SAndreas Jaekel 				perror("opening zev device failed");
1650e9a5e479SAndreas Jaekel 				return EXIT_FAILURE;
1651e9a5e479SAndreas Jaekel 			}
16524ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
16534ca7dd5eSAndreas Jaekel 			break;
16544ca7dd5eSAndreas Jaekel 		case 'q':
16554ca7dd5eSAndreas Jaekel 			snprintf(buf, sizeof(buf),
16564ca7dd5eSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
16574ca7dd5eSAndreas Jaekel 			close(fd);
16584ca7dd5eSAndreas Jaekel 			zev_device = buf;
16594ca7dd5eSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
16604ca7dd5eSAndreas Jaekel 			if (fd < 0) {
16614ca7dd5eSAndreas Jaekel 				perror("opening zev device failed");
16624ca7dd5eSAndreas Jaekel 				return EXIT_FAILURE;
16634ca7dd5eSAndreas Jaekel 			}
16644ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
16652bb8e5e2SAndreas Jaekel 			break;
1666797b8adfSArne Jansen 		case 'f':
1667797b8adfSArne Jansen 			fd = open(optarg, O_RDONLY);
1668797b8adfSArne Jansen 			if (fd < 0) {
1669797b8adfSArne Jansen 				perror("opening spool file failed");
1670797b8adfSArne Jansen 				return EXIT_FAILURE;
1671797b8adfSArne Jansen 			}
1672797b8adfSArne Jansen 			mode = MD_DUMP_SPOOL;
1673797b8adfSArne Jansen 			break;
1674e9a5e479SAndreas Jaekel 		case 'l':
16756a3d43bfSAndreas Jaekel 			mode = MD_LIST_QUEUES;
16766a3d43bfSAndreas Jaekel 			break;
1677e9a5e479SAndreas Jaekel 		case 'Q':
16786a3d43bfSAndreas Jaekel 			mode = MD_SET_GLOBAL_MAX_QUEUE_LEN;
16796a3d43bfSAndreas Jaekel 			arg = optarg;
16806a3d43bfSAndreas Jaekel 			break;
16814ca7dd5eSAndreas Jaekel 		case 'L':
16826a3d43bfSAndreas Jaekel 			mode = MD_SET_MAX_QUEUE_LEN;
16836a3d43bfSAndreas Jaekel 			arg = optarg;
16846a3d43bfSAndreas Jaekel 			arg2 = argv[optind];
16856a3d43bfSAndreas Jaekel 			break;
16860abdde4aSAndreas Jaekel 		case 'T':
16870abdde4aSAndreas Jaekel 			mode = MD_ZEVSTAT;
16880abdde4aSAndreas Jaekel 			arg = optarg;
16890abdde4aSAndreas Jaekel 			arg2 = argv[optind];
16900abdde4aSAndreas Jaekel 			break;
16919fd83c76SAndreas Jaekel 		case 'R':
16929fd83c76SAndreas Jaekel 			mode = MD_ZEV_REPORT;
16939fd83c76SAndreas Jaekel 			arg = optarg;
16949fd83c76SAndreas Jaekel 			break;
1695205a9bc9SAndreas Jaekel 		case 't':
16966a3d43bfSAndreas Jaekel 			mode = MD_SET_POLL_WAKEUP_QUEUE_LEN;
16976a3d43bfSAndreas Jaekel 			arg = optarg;
16986a3d43bfSAndreas Jaekel 			arg2 = argv[optind];
16996a3d43bfSAndreas Jaekel 			break;
17002bb8e5e2SAndreas Jaekel 		case 'm':
17016a3d43bfSAndreas Jaekel 			mode = MD_MUTE_POOL;
17026a3d43bfSAndreas Jaekel 			arg = optarg;
17036a3d43bfSAndreas Jaekel 			break;
17042bb8e5e2SAndreas Jaekel 		case 'M':
17056a3d43bfSAndreas Jaekel 			mode = MD_UNMUTE_POOL;
17066a3d43bfSAndreas Jaekel 			arg = optarg;
17076a3d43bfSAndreas Jaekel 			break;
170801c2c787SAndreas Jaekel 		case 'k':
17096a3d43bfSAndreas Jaekel 			mode = MD_MARK;
17106a3d43bfSAndreas Jaekel 			arg = optarg;
17116a3d43bfSAndreas Jaekel 			break;
1712e9a5e479SAndreas Jaekel 		case 'a':
17136a3d43bfSAndreas Jaekel 			mode = MD_ADD_QUEUE;
17146a3d43bfSAndreas Jaekel 			arg = optarg;
17156a3d43bfSAndreas Jaekel 			break;
17164ca7dd5eSAndreas Jaekel 		case 'A':
17176a3d43bfSAndreas Jaekel 			mode = MD_ADD_BLOCKING_QUEUE;
17186a3d43bfSAndreas Jaekel 			arg = optarg;
17196a3d43bfSAndreas Jaekel 			break;
1720e9a5e479SAndreas Jaekel 		case 'r':
17216a3d43bfSAndreas Jaekel 			mode = MD_REMOVE_QUEUE;
17226a3d43bfSAndreas Jaekel 			arg = optarg;
17236a3d43bfSAndreas Jaekel 			break;
1724e9a5e479SAndreas Jaekel 		case 'b':
17256a3d43bfSAndreas Jaekel 			mode = MD_QUEUE_BLOCKING;
17266a3d43bfSAndreas Jaekel 			arg = optarg;
17276a3d43bfSAndreas Jaekel 			break;
1728e9a5e479SAndreas Jaekel 		case 'B':
17296a3d43bfSAndreas Jaekel 			mode = MD_QUEUE_NONBLOCKING;
17306a3d43bfSAndreas Jaekel 			arg = optarg;
17316a3d43bfSAndreas Jaekel 			break;
1732e9a5e479SAndreas Jaekel 		case 'P':
17336a3d43bfSAndreas Jaekel 			mode = MD_QUEUE_PROPERTIES;
17346a3d43bfSAndreas Jaekel 			arg = optarg;
17356a3d43bfSAndreas Jaekel 			break;
1736c62d8367SAndreas Jaekel 		case 'V':
1737c62d8367SAndreas Jaekel 			mode = MD_GET_ZEV_VERSION;
1738c62d8367SAndreas Jaekel 			break;
1739*c07f6d81SArne Jansen 		case 'F':
1740*c07f6d81SArne Jansen 			do_flush = 1;
1741*c07f6d81SArne Jansen 			break;
17422bb8e5e2SAndreas Jaekel 		case 'h':
17432bb8e5e2SAndreas Jaekel 		case '?':
17442bb8e5e2SAndreas Jaekel 		default:
17452bb8e5e2SAndreas Jaekel 			usage(argv[0]);
17462bb8e5e2SAndreas Jaekel 		}
17472bb8e5e2SAndreas Jaekel 	}
17486a3d43bfSAndreas Jaekel 
17496a3d43bfSAndreas Jaekel 	switch (mode) {
17506a3d43bfSAndreas Jaekel 	case MD_STATISTICS:
17516a3d43bfSAndreas Jaekel 		return zev_statistics(fd);
17526a3d43bfSAndreas Jaekel 	case MD_POLL_EVENTS:
1753bfe96c74SAndreas Jaekel 		return zev_poll_events(fd, create_tmp_queue);
1754797b8adfSArne Jansen 	case MD_DUMP_SPOOL:
1755797b8adfSArne Jansen 		return zev_dump_spool(fd);
17566a3d43bfSAndreas Jaekel 	case MD_CHECKSUMS:
17576a3d43bfSAndreas Jaekel 		return zev_checksum(fd, arg);
17586a3d43bfSAndreas Jaekel 	case MD_DEBUG_INFO:
17596a3d43bfSAndreas Jaekel 		return zev_debug_info(fd);
17606a3d43bfSAndreas Jaekel 	case MD_LIST_QUEUES:
17616a3d43bfSAndreas Jaekel 		return zev_list_queues(fd);
17626a3d43bfSAndreas Jaekel 	case MD_SET_GLOBAL_MAX_QUEUE_LEN:
17636a3d43bfSAndreas Jaekel 		return zev_set_global_max_queue_len(fd, arg);
17646a3d43bfSAndreas Jaekel 	case MD_SET_MAX_QUEUE_LEN:
17656a3d43bfSAndreas Jaekel 		return zev_set_max_queue_len(fd, arg, arg2);
17666a3d43bfSAndreas Jaekel 	case MD_SET_POLL_WAKEUP_QUEUE_LEN:
17676a3d43bfSAndreas Jaekel 		return zev_set_poll_wakeup_queue_len(fd, arg, arg2);
17680abdde4aSAndreas Jaekel 	case MD_ZEVSTAT:
17699fd83c76SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
17709fd83c76SAndreas Jaekel 	case MD_ZEV_REPORT:
17719fd83c76SAndreas Jaekel 		return zev_report(fd, arg);
17726a3d43bfSAndreas Jaekel 	case MD_MUTE_POOL:
17736a3d43bfSAndreas Jaekel 		return zev_mute_pool(fd, arg);
17746a3d43bfSAndreas Jaekel 	case MD_UNMUTE_POOL:
17756a3d43bfSAndreas Jaekel 		return zev_unmute_pool(fd, arg);
17766a3d43bfSAndreas Jaekel 	case MD_MARK:
17776a3d43bfSAndreas Jaekel 		return zev_mark(fd, arg);
17786a3d43bfSAndreas Jaekel 	case MD_ADD_QUEUE:
17796a3d43bfSAndreas Jaekel 		return zev_add_queue(fd, arg, 0);
17806a3d43bfSAndreas Jaekel 	case MD_ADD_BLOCKING_QUEUE:
17816a3d43bfSAndreas Jaekel 		return zev_add_queue(fd, arg, 1);
17826a3d43bfSAndreas Jaekel 	case MD_REMOVE_QUEUE:
17836a3d43bfSAndreas Jaekel 		return zev_remove_queue(fd, arg);
17846a3d43bfSAndreas Jaekel 	case MD_QUEUE_BLOCKING:
17856a3d43bfSAndreas Jaekel 		return zev_queue_blocking(fd, arg, 0);
17866a3d43bfSAndreas Jaekel 	case MD_QUEUE_NONBLOCKING:
17876a3d43bfSAndreas Jaekel 		return zev_queue_blocking(fd, arg, 1);
17886a3d43bfSAndreas Jaekel 	case MD_QUEUE_PROPERTIES:
17896a3d43bfSAndreas Jaekel 		return zev_queue_properties(fd, arg);
1790c62d8367SAndreas Jaekel 	case MD_GET_ZEV_VERSION:
1791c62d8367SAndreas Jaekel 		return zev_get_zev_version(fd);
17926a3d43bfSAndreas Jaekel 	default:
17932bb8e5e2SAndreas Jaekel 		close(fd);
17946a3d43bfSAndreas Jaekel 		usage(argv[0]);
1795e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
17966a3d43bfSAndreas Jaekel 	};
17972bb8e5e2SAndreas Jaekel }
17982bb8e5e2SAndreas Jaekel 
1799