xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision 8cfb36b9cea377562b16f9416959316b048f129e)
1a18c35b9SAndreas Jaekel #include <stdio.h>
2a18c35b9SAndreas Jaekel #include <unistd.h>
3a18c35b9SAndreas Jaekel #include <stdlib.h>
4a18c35b9SAndreas Jaekel #include <fcntl.h>
5a18c35b9SAndreas Jaekel #include <stropts.h>
6a18c35b9SAndreas Jaekel #include <poll.h>
7a18c35b9SAndreas Jaekel #include <string.h>
8a18c35b9SAndreas Jaekel #include <sys/fs/zev.h>
9a18c35b9SAndreas Jaekel #include <errno.h>
1042110aacSAndreas Jaekel #include <sys/sysmacros.h>
1116ff6b2fSAndreas Jaekel #include <stdarg.h>
12b690436dSAndreas Jaekel #include <sys/avl.h>
13f432e238SAndreas Jaekel #include <sys/stat.h>
14a18c35b9SAndreas Jaekel 
15add9520fSAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
16a18c35b9SAndreas Jaekel 
17b690436dSAndreas Jaekel #if !defined(offsetof)
18b690436dSAndreas Jaekel #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
19b690436dSAndreas Jaekel #endif
20b690436dSAndreas Jaekel 
21a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
22342055d2SArne Jansen static int do_flush = 0;
23a18c35b9SAndreas Jaekel 
24aafc540fSAndreas Jaekel static char *zev_op_name[] = {
2516ff6b2fSAndreas Jaekel 	"ERROR",
2616ff6b2fSAndreas Jaekel 	"MARK",
2716ff6b2fSAndreas Jaekel 	"ZFS_MOUNT",
2816ff6b2fSAndreas Jaekel 	"ZFS_UMOUNT",
2916ff6b2fSAndreas Jaekel 	"ZVOL_WRITE",
3016ff6b2fSAndreas Jaekel 	"ZVOL_TRUNCATE",
3116ff6b2fSAndreas Jaekel 	"ZNODE_CLOSE_AFTER_UPDATE",
3216ff6b2fSAndreas Jaekel 	"ZNODE_CREATE",
3316ff6b2fSAndreas Jaekel 	"ZNODE_MKDIR",
3416ff6b2fSAndreas Jaekel 	"ZNODE_MAKE_XATTR_DIR",
3516ff6b2fSAndreas Jaekel 	"ZNODE_REMOVE",
3616ff6b2fSAndreas Jaekel 	"ZNODE_RMDIR",
3716ff6b2fSAndreas Jaekel 	"ZNODE_LINK",
3816ff6b2fSAndreas Jaekel 	"ZNODE_SYMLINK",
3916ff6b2fSAndreas Jaekel 	"ZNODE_RENAME",
4016ff6b2fSAndreas Jaekel 	"ZNODE_WRITE",
4116ff6b2fSAndreas Jaekel 	"ZNODE_TRUNCATE",
4216ff6b2fSAndreas Jaekel 	"ZNODE_SETATTR",
4316ff6b2fSAndreas Jaekel 	"ZNODE_ACL",
44aafc540fSAndreas Jaekel 	NULL
45aafc540fSAndreas Jaekel };
46aafc540fSAndreas Jaekel 
47a5090b97SAndreas Jaekel #define MD_STATISTICS			1
48a5090b97SAndreas Jaekel #define MD_POLL_EVENTS			2
49a5090b97SAndreas Jaekel #define MD_CHECKSUMS			3
50a5090b97SAndreas Jaekel #define MD_DEBUG_INFO			4
51a5090b97SAndreas Jaekel #define MD_LIST_QUEUES			5
52a5090b97SAndreas Jaekel #define MD_SET_GLOBAL_MAX_QUEUE_LEN	6
53a5090b97SAndreas Jaekel #define MD_SET_MAX_QUEUE_LEN		7
54a5090b97SAndreas Jaekel #define MD_SET_POLL_WAKEUP_QUEUE_LEN	8
55a5090b97SAndreas Jaekel #define MD_MUTE_POOL			9
56a5090b97SAndreas Jaekel #define MD_UNMUTE_POOL			10
57a5090b97SAndreas Jaekel #define MD_MARK				11
58a5090b97SAndreas Jaekel #define MD_ADD_QUEUE			12
59a5090b97SAndreas Jaekel #define MD_ADD_BLOCKING_QUEUE		13
60a5090b97SAndreas Jaekel #define MD_REMOVE_QUEUE			14
61a5090b97SAndreas Jaekel #define MD_QUEUE_BLOCKING		15
62a5090b97SAndreas Jaekel #define MD_QUEUE_NONBLOCKING		16
63a5090b97SAndreas Jaekel #define MD_QUEUE_PROPERTIES		17
64b690436dSAndreas Jaekel #define MD_ZEVSTAT			18
65f432e238SAndreas Jaekel #define MD_ZEV_REPORT			19
6635526fb3SArne Jansen #define MD_DUMP_SPOOL			20
67e3455c18SAndreas Jaekel #define MD_GET_ZEV_VERSION		21
68a5090b97SAndreas Jaekel 
69205ed6bfSAndreas Jaekel static int verbose = 0;
7016ff6b2fSAndreas Jaekel static int grep_friendly = 0;
7116ff6b2fSAndreas Jaekel 
72*8cfb36b9SArne Jansen #define MAX_GUID 10000
73*8cfb36b9SArne Jansen static int num_guid_filter = 0;
74*8cfb36b9SArne Jansen static uint64_t guid_filter[MAX_GUID];
75*8cfb36b9SArne Jansen 
7616ff6b2fSAndreas Jaekel static void
zpf(char * fmt,...)7716ff6b2fSAndreas Jaekel zpf(char *fmt, ...)
7816ff6b2fSAndreas Jaekel {
7916ff6b2fSAndreas Jaekel 	va_list	ap;
8016ff6b2fSAndreas Jaekel 
8116ff6b2fSAndreas Jaekel 	va_start(ap, fmt);
8216ff6b2fSAndreas Jaekel 	vprintf(fmt, ap);
8316ff6b2fSAndreas Jaekel 	va_end(ap);
8416ff6b2fSAndreas Jaekel 	if (grep_friendly) {
8516ff6b2fSAndreas Jaekel 		printf(" ");
8616ff6b2fSAndreas Jaekel 	} else {
8716ff6b2fSAndreas Jaekel 		printf("\n");
8816ff6b2fSAndreas Jaekel 	}
8916ff6b2fSAndreas Jaekel }
9016ff6b2fSAndreas Jaekel 
9116ff6b2fSAndreas Jaekel static void
znl(void)9216ff6b2fSAndreas Jaekel znl(void)
9316ff6b2fSAndreas Jaekel {
9416ff6b2fSAndreas Jaekel 	if (grep_friendly)
9516ff6b2fSAndreas Jaekel 		printf("\n");
9616ff6b2fSAndreas Jaekel }
97205ed6bfSAndreas Jaekel 
982eabeab5SAndreas Jaekel static void
sig2hex_direct(const uint8_t * sig,char * hex)992eabeab5SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
1002eabeab5SAndreas Jaekel {
1012eabeab5SAndreas Jaekel 	int     i;
1022eabeab5SAndreas Jaekel 
1032eabeab5SAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
1042eabeab5SAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
1052eabeab5SAndreas Jaekel 	}
1062eabeab5SAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
1072eabeab5SAndreas Jaekel }
1082eabeab5SAndreas Jaekel 
109add9520fSAndreas Jaekel static int
zev_statistics(int fd)110a18c35b9SAndreas Jaekel zev_statistics(int fd)
111a18c35b9SAndreas Jaekel {
112a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
113add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
114a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
115add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
116a18c35b9SAndreas Jaekel 	}
117a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
118a18c35b9SAndreas Jaekel 
119a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
120a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
121a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
122a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
123a18c35b9SAndreas Jaekel 
124add9520fSAndreas Jaekel 	printf("    discarded events        : %lu\n",
125add9520fSAndreas Jaekel 	    zs.zev_cnt_discarded_events);
126add9520fSAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
127add9520fSAndreas Jaekel 
128a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
129a18c35b9SAndreas Jaekel 
130a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
131a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
132a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
133a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
134a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
135a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
136a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
137a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
138a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
139a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
140a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
141a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
142a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
143a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
144a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
145a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
146a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
147add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
148a18c35b9SAndreas Jaekel }
149a18c35b9SAndreas Jaekel 
150a18c35b9SAndreas Jaekel static void
zev_print_inode_info(char * name,zev_inode_info_t * info)15116ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info)
15216ff6b2fSAndreas Jaekel {
15316ff6b2fSAndreas Jaekel 	zpf("  %s.inode: %llu", name, info->ino);
15416ff6b2fSAndreas Jaekel 	zpf("  %s.gen: %llu", name, info->gen);
15516ff6b2fSAndreas Jaekel 	zpf("  %s.mtime: %llu", name, info->mtime);
15616ff6b2fSAndreas Jaekel 	zpf("  %s.ctime: %llu", name, info->ctime);
15716ff6b2fSAndreas Jaekel 	zpf("  %s.size: %llu", name, info->size);
15816ff6b2fSAndreas Jaekel 	zpf("  %s.mode: %llo", name, info->mode);
15916ff6b2fSAndreas Jaekel 	zpf("  %s.links: %llu", name, info->links);
16016ff6b2fSAndreas Jaekel 	zpf("  %s.type: %lu", name, info->type);
16116ff6b2fSAndreas Jaekel 	zpf("  %s.flags: %lu", name, info->flags);
16216ff6b2fSAndreas Jaekel }
16316ff6b2fSAndreas Jaekel 
16416ff6b2fSAndreas Jaekel static void
zev_print_mark_payload(zev_mark_t * rec)16516ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec)
16616ff6b2fSAndreas Jaekel {
16716ff6b2fSAndreas Jaekel 	int i;
16816ff6b2fSAndreas Jaekel 	int j;
16916ff6b2fSAndreas Jaekel 	uint8_t *p;
17016ff6b2fSAndreas Jaekel 	char c;
17116ff6b2fSAndreas Jaekel 
17216ff6b2fSAndreas Jaekel 	zpf("  payload:");
17316ff6b2fSAndreas Jaekel 	p = (uint8_t *)ZEV_PAYLOAD(rec);
17416ff6b2fSAndreas Jaekel 	for (i=0; i<rec->payload_len; i+=16) {
17516ff6b2fSAndreas Jaekel 		printf("  ");
17616ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
17716ff6b2fSAndreas Jaekel 			printf("%02x ", p[j]);
17816ff6b2fSAndreas Jaekel 			if (j == i + 7)
17916ff6b2fSAndreas Jaekel 				printf(" ");
18016ff6b2fSAndreas Jaekel 		}
18116ff6b2fSAndreas Jaekel 		if (grep_friendly)
18216ff6b2fSAndreas Jaekel 			continue;
18316ff6b2fSAndreas Jaekel 		for (; j<i+16; j++) {
18416ff6b2fSAndreas Jaekel 			printf("   ");
18516ff6b2fSAndreas Jaekel 			if (j == i + 7)
18616ff6b2fSAndreas Jaekel 				printf(" ");
18716ff6b2fSAndreas Jaekel 		}
18816ff6b2fSAndreas Jaekel 		printf("    ");
18916ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
19016ff6b2fSAndreas Jaekel 			c = '.';
19116ff6b2fSAndreas Jaekel 			if (p[j] >= ' ' && p[j] <= '~')
19216ff6b2fSAndreas Jaekel 				c = p[j];
19316ff6b2fSAndreas Jaekel 			printf("%c", c);
19416ff6b2fSAndreas Jaekel 			if (j == i + 7)
19516ff6b2fSAndreas Jaekel 				printf(" ");
19616ff6b2fSAndreas Jaekel 		}
19716ff6b2fSAndreas Jaekel 		printf("\n");
19816ff6b2fSAndreas Jaekel 	}
19916ff6b2fSAndreas Jaekel }
20016ff6b2fSAndreas Jaekel 
20116ff6b2fSAndreas Jaekel static void
zev_print_error(char * buf)202f2dd45e5SAndreas Jaekel zev_print_error(char *buf)
203f2dd45e5SAndreas Jaekel {
204f2dd45e5SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
205f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
206f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
207f2dd45e5SAndreas Jaekel 
20816ff6b2fSAndreas Jaekel 	if (verbose) {
20916ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
21016ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
21116ff6b2fSAndreas Jaekel 		zpf("  failed.op: %s",
21216ff6b2fSAndreas Jaekel 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
21316ff6b2fSAndreas Jaekel 		zpf("  message: %s", ZEV_ERRSTR(rec));
21416ff6b2fSAndreas Jaekel 		znl();
21516ff6b2fSAndreas Jaekel 	} else {
216f2dd45e5SAndreas Jaekel 		printf("%s %s: failed_op=%s msg=%s\n",
217f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
21816ff6b2fSAndreas Jaekel 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
21916ff6b2fSAndreas Jaekel 		       ZEV_ERRSTR(rec));
22016ff6b2fSAndreas Jaekel 	}
221f2dd45e5SAndreas Jaekel }
222f2dd45e5SAndreas Jaekel 
223f2dd45e5SAndreas Jaekel static void
zev_print_mark(char * buf)224888fea18SAndreas Jaekel zev_print_mark(char *buf)
225888fea18SAndreas Jaekel {
226888fea18SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
227888fea18SAndreas Jaekel 	time_t op_time = rec->op_time;
228888fea18SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
229888fea18SAndreas Jaekel 
23016ff6b2fSAndreas Jaekel 	if (verbose) {
23116ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
23216ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
23316ff6b2fSAndreas Jaekel 		zpf("  mark.id: %llu", rec->mark_id);
23416ff6b2fSAndreas Jaekel 		zpf("  payload.len: %llu", rec->payload_len);
23516ff6b2fSAndreas Jaekel 		if (rec->payload_len)
23616ff6b2fSAndreas Jaekel 			zev_print_mark_payload(rec);
23716ff6b2fSAndreas Jaekel 		znl();
23816ff6b2fSAndreas Jaekel 	} else {
239647b4f9eSJan Schlien 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld "
240647b4f9eSJan Schlien 		       "payload=\"%.*s\"\n",
24116ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
242647b4f9eSJan Schlien 		       rec->mark_id, rec->payload_len,
243647b4f9eSJan Schlien 		       rec->payload_len, (char *)(rec + 1));
24416ff6b2fSAndreas Jaekel 	}
245888fea18SAndreas Jaekel }
246888fea18SAndreas Jaekel 
247888fea18SAndreas Jaekel static void
zev_print_zfs_mount(char * buf)248f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf)
249f2dd45e5SAndreas Jaekel {
250f2dd45e5SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
251f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
252f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
253f2dd45e5SAndreas Jaekel 
25416ff6b2fSAndreas Jaekel 	if (verbose) {
25516ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
25616ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
25703a64974SSimon Klinkert 		zpf("  txg: %llu", rec->txg);
25816ff6b2fSAndreas Jaekel 		zpf("  dataset: %s", ZEV_DATASET(rec));
25916ff6b2fSAndreas Jaekel 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
26016ff6b2fSAndreas Jaekel 		zpf("  remount: %s", rec->remount ? "true" : "false");
26116ff6b2fSAndreas Jaekel 		zev_print_inode_info("root", &rec->root);
26216ff6b2fSAndreas Jaekel 		znl();
26316ff6b2fSAndreas Jaekel 	} else {
26416ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
26516ff6b2fSAndreas Jaekel 		       "mountpoint='%s'\n",
266f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
267f2dd45e5SAndreas Jaekel 		       rec->guid,
268f2dd45e5SAndreas Jaekel 		       rec->remount ? "true" : "false",
269f2dd45e5SAndreas Jaekel 		       ZEV_DATASET(rec),
270f2dd45e5SAndreas Jaekel 		       ZEV_MOUNTPOINT(rec));
271f2dd45e5SAndreas Jaekel 	}
27216ff6b2fSAndreas Jaekel }
273f2dd45e5SAndreas Jaekel 
274f2dd45e5SAndreas Jaekel static void
zev_print_zfs_umount(char * buf)275f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf)
276f2dd45e5SAndreas Jaekel {
277f2dd45e5SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
278f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
279f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
280f2dd45e5SAndreas Jaekel 
28116ff6b2fSAndreas Jaekel 	if (verbose) {
28216ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
28316ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
28403a64974SSimon Klinkert 		zpf("  txg: %llu", rec->txg);
28594875cb8SAndreas Jaekel 		zev_print_inode_info("covered", &rec->covered);
28616ff6b2fSAndreas Jaekel 		znl();
28716ff6b2fSAndreas Jaekel 	} else {
288f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
289f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
290f2dd45e5SAndreas Jaekel 		       rec->guid);
291f2dd45e5SAndreas Jaekel 	}
29216ff6b2fSAndreas Jaekel }
293f2dd45e5SAndreas Jaekel 
294f2dd45e5SAndreas Jaekel static void
zev_print_zvol_truncate(char * buf)295f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf)
296f2dd45e5SAndreas Jaekel {
297f2dd45e5SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
298f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
299f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
300f2dd45e5SAndreas Jaekel 
30116ff6b2fSAndreas Jaekel 	if (verbose) {
30216ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
30316ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
30412119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
30516ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
30616ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
30716ff6b2fSAndreas Jaekel 		znl();
30816ff6b2fSAndreas Jaekel 	} else {
309f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
310f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
311f2dd45e5SAndreas Jaekel 		       rec->guid,
312f2dd45e5SAndreas Jaekel 		       rec->offset,
313f2dd45e5SAndreas Jaekel 		       rec->length);
314f2dd45e5SAndreas Jaekel 	}
31516ff6b2fSAndreas Jaekel }
316f2dd45e5SAndreas Jaekel 
317f2dd45e5SAndreas Jaekel static void
zev_print_zvol_write(char * buf)318f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf)
319f2dd45e5SAndreas Jaekel {
320f2dd45e5SAndreas Jaekel 	zev_print_zvol_truncate(buf);
321f2dd45e5SAndreas Jaekel }
322f2dd45e5SAndreas Jaekel 
323f2dd45e5SAndreas Jaekel static void
zev_print_znode_close_after_update(char * buf)324f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
325f2dd45e5SAndreas Jaekel {
326f2dd45e5SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
327f2dd45e5SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
328f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
329f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
330f2dd45e5SAndreas Jaekel 
33116ff6b2fSAndreas Jaekel 	if (verbose) {
33216ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
33316ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
33416ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
33516ff6b2fSAndreas Jaekel 		znl();
33616ff6b2fSAndreas Jaekel 	} else {
337f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
338f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
339f2dd45e5SAndreas Jaekel 		       rec->guid,
340f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
341f2dd45e5SAndreas Jaekel 	}
34216ff6b2fSAndreas Jaekel }
343f2dd45e5SAndreas Jaekel 
344f2dd45e5SAndreas Jaekel static void
zev_print_znode_create(char * buf)345f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf)
346f2dd45e5SAndreas Jaekel {
347f2dd45e5SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
348f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
349f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
3502eabeab5SAndreas Jaekel 	zev_sig_t *sig;
3512eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
352f2dd45e5SAndreas Jaekel 
35316ff6b2fSAndreas Jaekel 	if (verbose) {
35416ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
35516ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
35612119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
35716ff6b2fSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
3582eabeab5SAndreas Jaekel 		sig = &rec->signature;
3592eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
3602eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
3612eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
36216ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
36312119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
36416ff6b2fSAndreas Jaekel 		znl();
36516ff6b2fSAndreas Jaekel 	} else {
36635d4e8ddSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
36735d4e8ddSAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
368f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
369f2dd45e5SAndreas Jaekel 		       rec->guid,
370f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
371f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
37235d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
373f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
374f2dd45e5SAndreas Jaekel 	}
37516ff6b2fSAndreas Jaekel }
376f2dd45e5SAndreas Jaekel 
377f2dd45e5SAndreas Jaekel static void
zev_print_znode_mkdir(char * buf)378f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf)
379f2dd45e5SAndreas Jaekel {
380f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
381f2dd45e5SAndreas Jaekel }
382f2dd45e5SAndreas Jaekel 
383f2dd45e5SAndreas Jaekel static void
zev_print_znode_make_xattr_dir(char * buf)384f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
385f2dd45e5SAndreas Jaekel {
386f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
387f2dd45e5SAndreas Jaekel }
388f2dd45e5SAndreas Jaekel 
389f2dd45e5SAndreas Jaekel static void
zev_print_znode_remove(char * buf)390f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf)
391f2dd45e5SAndreas Jaekel {
392f2dd45e5SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
393f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
394f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
395f2dd45e5SAndreas Jaekel 
39616ff6b2fSAndreas Jaekel 	if (verbose) {
39716ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
39816ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
39912119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
40016ff6b2fSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
40116ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
40212119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
40316ff6b2fSAndreas Jaekel 		znl();
40416ff6b2fSAndreas Jaekel 	} else {
40516ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
40616ff6b2fSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
407f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
408f2dd45e5SAndreas Jaekel 		       rec->guid,
409f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
41097dcf88dSAndreas Jaekel 		       rec->file.mtime,
411f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
412f2dd45e5SAndreas Jaekel 	}
41316ff6b2fSAndreas Jaekel }
414f2dd45e5SAndreas Jaekel 
415f2dd45e5SAndreas Jaekel static void
zev_print_znode_rmdir(char * buf)416f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf)
417f2dd45e5SAndreas Jaekel {
418f2dd45e5SAndreas Jaekel 	zev_print_znode_remove(buf);
419f2dd45e5SAndreas Jaekel }
420f2dd45e5SAndreas Jaekel 
421f2dd45e5SAndreas Jaekel static void
zev_print_znode_link(char * buf)422f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf)
423f2dd45e5SAndreas Jaekel {
424f2dd45e5SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
425f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
426f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
427f2dd45e5SAndreas Jaekel 
42816ff6b2fSAndreas Jaekel 	if (verbose) {
42916ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
43016ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
43112119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
43216ff6b2fSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
43316ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
43412119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
43516ff6b2fSAndreas Jaekel 		znl();
43616ff6b2fSAndreas Jaekel 	} else {
437a01b300aSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
438a01b300aSAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
439f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
440f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
441f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
442a01b300aSAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
443f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
44416ff6b2fSAndreas Jaekel 	}
445f2dd45e5SAndreas Jaekel }
446f2dd45e5SAndreas Jaekel 
447f2dd45e5SAndreas Jaekel static void
zev_print_znode_symlink(char * buf)448f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf)
449f2dd45e5SAndreas Jaekel {
450f2dd45e5SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
451f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
452f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
4532eabeab5SAndreas Jaekel 	zev_sig_t *sig;
4542eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
455f2dd45e5SAndreas Jaekel 
45616ff6b2fSAndreas Jaekel 	if (verbose) {
45716ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
45816ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
45912119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
46016ff6b2fSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
46116ff6b2fSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
4622eabeab5SAndreas Jaekel 		sig = &rec->signature;
4632eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
4642eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
4652eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
46616ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
46712119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
46816ff6b2fSAndreas Jaekel 		znl();
46916ff6b2fSAndreas Jaekel 	} else {
47016ff6b2fSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
47116ff6b2fSAndreas Jaekel 		       "name='%s' link='%s'\n",
472f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
473f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
474f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
475f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec),
476f2dd45e5SAndreas Jaekel 		       ZEV_LINK(rec));
477f2dd45e5SAndreas Jaekel 	}
47816ff6b2fSAndreas Jaekel }
479f2dd45e5SAndreas Jaekel 
480f2dd45e5SAndreas Jaekel static void
zev_print_znode_rename(char * buf)481f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf)
482f2dd45e5SAndreas Jaekel {
483f2dd45e5SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
484f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
485f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
486f2dd45e5SAndreas Jaekel 
48716ff6b2fSAndreas Jaekel 	if (verbose) {
48816ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
48916ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
49012119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
49116ff6b2fSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
49216ff6b2fSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
49316ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
4948aa47a6bSAndreas Jaekel 		if (rec->clobbered_file.ino)
4958aa47a6bSAndreas Jaekel 			zev_print_inode_info("clobbered_file",
4968aa47a6bSAndreas Jaekel 			                     &rec->clobbered_file);
49716ff6b2fSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
49816ff6b2fSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
49916ff6b2fSAndreas Jaekel 		znl();
50016ff6b2fSAndreas Jaekel 	} else {
50116ff6b2fSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
50216ff6b2fSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
50316ff6b2fSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
50416ff6b2fSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
505f2dd45e5SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
506f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
507f2dd45e5SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
508f2dd45e5SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
509f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
51035d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
51135d4e8ddSAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
51235d4e8ddSAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
513f2dd45e5SAndreas Jaekel 		       ZEV_SRCNAME(rec),
514f2dd45e5SAndreas Jaekel 		       ZEV_DSTNAME(rec));
515f2dd45e5SAndreas Jaekel 	}
51616ff6b2fSAndreas Jaekel }
517f2dd45e5SAndreas Jaekel 
518f2dd45e5SAndreas Jaekel static void
zev_print_znode_write(char * buf)519f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf)
520f2dd45e5SAndreas Jaekel {
521f2dd45e5SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
522f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
523f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
524205ed6bfSAndreas Jaekel 	zev_sig_t *sig;
525205ed6bfSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
526205ed6bfSAndreas Jaekel 	int i;
527f2dd45e5SAndreas Jaekel 
528205ed6bfSAndreas Jaekel 	if (verbose) {
52916ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
53016ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
53112119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
53216ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
53316ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
53416ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
53516ff6b2fSAndreas Jaekel 		znl();
536205ed6bfSAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
537205ed6bfSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
538205ed6bfSAndreas Jaekel 			sig += i;
539205ed6bfSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
5402eabeab5SAndreas Jaekel 			zpf("  sig: level %d, offset %llu, value %s",
541205ed6bfSAndreas Jaekel 			    sig->level, sig->block_offset, sigval);
542205ed6bfSAndreas Jaekel 		}
54316ff6b2fSAndreas Jaekel 	} else {
54416ff6b2fSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
54516ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
54616ff6b2fSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
54716ff6b2fSAndreas Jaekel 		       rec->offset, rec->length);
548205ed6bfSAndreas Jaekel 	}
549f2dd45e5SAndreas Jaekel }
550f2dd45e5SAndreas Jaekel 
551f2dd45e5SAndreas Jaekel static void
zev_print_znode_truncate(char * buf)552f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf)
553f2dd45e5SAndreas Jaekel {
554f2dd45e5SAndreas Jaekel 	zev_print_znode_write(buf);
555f2dd45e5SAndreas Jaekel }
556f2dd45e5SAndreas Jaekel 
557f2dd45e5SAndreas Jaekel static void
zev_print_znode_setattr(char * buf)558f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf)
559f2dd45e5SAndreas Jaekel {
560f2dd45e5SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
561f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
562f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
563f2dd45e5SAndreas Jaekel 
56416ff6b2fSAndreas Jaekel 	if (verbose) {
56516ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
56616ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
56712119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
56816ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
56916ff6b2fSAndreas Jaekel 		znl();
57016ff6b2fSAndreas Jaekel 	} else {
57135d4e8ddSAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
572f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
57335d4e8ddSAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
574f2dd45e5SAndreas Jaekel 	}
57516ff6b2fSAndreas Jaekel }
576f2dd45e5SAndreas Jaekel 
577f2dd45e5SAndreas Jaekel static void
zev_print_znode_acl(char * buf)578f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf)
579f2dd45e5SAndreas Jaekel {
580f2dd45e5SAndreas Jaekel 	zev_print_znode_setattr(buf);
581f2dd45e5SAndreas Jaekel }
582f2dd45e5SAndreas Jaekel 
583f2dd45e5SAndreas Jaekel static void
zev_print_event(char * buf,int len)584aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
585aafc540fSAndreas Jaekel {
586f2dd45e5SAndreas Jaekel 	int record_len;
587f2dd45e5SAndreas Jaekel 	int op;
588aafc540fSAndreas Jaekel 
589f2dd45e5SAndreas Jaekel 	record_len = *(uint32_t *)buf;
590f2dd45e5SAndreas Jaekel 	if (record_len != len) {
591f2dd45e5SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
592f2dd45e5SAndreas Jaekel 		        record_len, len);
593aafc540fSAndreas Jaekel 		exit(1);
594aafc540fSAndreas Jaekel 	}
595f2dd45e5SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
596aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
597f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
598aafc540fSAndreas Jaekel 		exit(1);
599aafc540fSAndreas Jaekel 	}
600*8cfb36b9SArne Jansen 	if (num_guid_filter) {
601*8cfb36b9SArne Jansen 		uint64_t guid = *((uint64_t *)buf + 2);
602*8cfb36b9SArne Jansen 		int i;
603*8cfb36b9SArne Jansen 
604*8cfb36b9SArne Jansen 		for (i = 0; i < num_guid_filter; ++i)
605*8cfb36b9SArne Jansen 			if (guid_filter[i] == guid)
606*8cfb36b9SArne Jansen 				break;
607*8cfb36b9SArne Jansen 
608*8cfb36b9SArne Jansen 		if (i == num_guid_filter)
609*8cfb36b9SArne Jansen 			/* no match, filtered */
610*8cfb36b9SArne Jansen 			return;
611*8cfb36b9SArne Jansen 	}
612f2dd45e5SAndreas Jaekel 	switch (op) {
613f2dd45e5SAndreas Jaekel 	case ZEV_OP_ERROR:
614f2dd45e5SAndreas Jaekel 		zev_print_error(buf);
615aafc540fSAndreas Jaekel 		break;
616888fea18SAndreas Jaekel 	case ZEV_OP_MARK:
617888fea18SAndreas Jaekel 		zev_print_mark(buf);
618888fea18SAndreas Jaekel 		break;
619f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
620f2dd45e5SAndreas Jaekel 		zev_print_zfs_mount(buf);
621aafc540fSAndreas Jaekel 		break;
622f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
623f2dd45e5SAndreas Jaekel 		zev_print_zfs_umount(buf);
624aafc540fSAndreas Jaekel 		break;
625f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
626f2dd45e5SAndreas Jaekel 		zev_print_zvol_truncate(buf);
627aafc540fSAndreas Jaekel 		break;
628f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
629f2dd45e5SAndreas Jaekel 		zev_print_zvol_write(buf);
630f2dd45e5SAndreas Jaekel 		break;
631f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
632f2dd45e5SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
633f2dd45e5SAndreas Jaekel 		break;
634f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
635f2dd45e5SAndreas Jaekel 		zev_print_znode_create(buf);
636f2dd45e5SAndreas Jaekel 		break;
637f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
638f2dd45e5SAndreas Jaekel 		zev_print_znode_mkdir(buf);
639f2dd45e5SAndreas Jaekel 		break;
640f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
641f2dd45e5SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
642f2dd45e5SAndreas Jaekel 		break;
643f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
644f2dd45e5SAndreas Jaekel 		zev_print_znode_remove(buf);
645f2dd45e5SAndreas Jaekel 		break;
646f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
647f2dd45e5SAndreas Jaekel 		zev_print_znode_rmdir(buf);
648f2dd45e5SAndreas Jaekel 		break;
649f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
650f2dd45e5SAndreas Jaekel 		zev_print_znode_link(buf);
651f2dd45e5SAndreas Jaekel 		break;
652f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
653f2dd45e5SAndreas Jaekel 		zev_print_znode_symlink(buf);
654f2dd45e5SAndreas Jaekel 		break;
655f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
656f2dd45e5SAndreas Jaekel 		zev_print_znode_rename(buf);
657f2dd45e5SAndreas Jaekel 		break;
658f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
659f2dd45e5SAndreas Jaekel 		zev_print_znode_write(buf);
660f2dd45e5SAndreas Jaekel 		break;
661f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
662f2dd45e5SAndreas Jaekel 		zev_print_znode_truncate(buf);
663f2dd45e5SAndreas Jaekel 		break;
664f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
665f2dd45e5SAndreas Jaekel 		zev_print_znode_setattr(buf);
666f2dd45e5SAndreas Jaekel 		break;
667f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
668f2dd45e5SAndreas Jaekel 		zev_print_znode_acl(buf);
669aafc540fSAndreas Jaekel 		break;
670aafc540fSAndreas Jaekel 	default:
671f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
672aafc540fSAndreas Jaekel 		exit(1);
673aafc540fSAndreas Jaekel 	}
674342055d2SArne Jansen 	if (do_flush)
675342055d2SArne Jansen 		fflush(stdout);
676aafc540fSAndreas Jaekel }
677aafc540fSAndreas Jaekel 
678add9520fSAndreas Jaekel static int
zev_poll_events(int fd,int create_tmp_queue)679b64581b1SAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
680a18c35b9SAndreas Jaekel {
681a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
682a18c35b9SAndreas Jaekel 	int ret;
683aafc540fSAndreas Jaekel 	char buf[4096];
684d979f56cSAndreas Jaekel 	zev_event_t *ev;
685d979f56cSAndreas Jaekel 	int off = 0;
686add9520fSAndreas Jaekel 	int q_fd;
687add9520fSAndreas Jaekel 
6886a6a51eeSAndreas Jaekel 	if (create_tmp_queue) {
6896a6a51eeSAndreas Jaekel 		snprintf(buf, sizeof(buf),
690b64581b1SAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", ZEV_TMPQUEUE_DEVICE_NAME);
691add9520fSAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
692add9520fSAndreas Jaekel 		if (q_fd < 0) {
693add9520fSAndreas Jaekel 			perror("opening queue device failed");
694add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
695add9520fSAndreas Jaekel 		}
6966a6a51eeSAndreas Jaekel 	} else {
6976a6a51eeSAndreas Jaekel 		q_fd = fd;
6986a6a51eeSAndreas Jaekel 	}
699add9520fSAndreas Jaekel 
700a18c35b9SAndreas Jaekel 	while (1) {
701add9520fSAndreas Jaekel 		pfd[0].fd = q_fd;
702a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
703a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
704a18c35b9SAndreas Jaekel 		if (ret < 0) {
705a18c35b9SAndreas Jaekel 			perror("poll failed");
7066a6a51eeSAndreas Jaekel 			close(q_fd);
707add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
708a18c35b9SAndreas Jaekel 		}
709a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
710a18c35b9SAndreas Jaekel 			continue;
711a18c35b9SAndreas Jaekel 		/* data available */
712add9520fSAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
713a18c35b9SAndreas Jaekel 		if (ret < 0) {
714a18c35b9SAndreas Jaekel 			perror("read failed");
7156a6a51eeSAndreas Jaekel 			close(q_fd);
716add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
717a18c35b9SAndreas Jaekel 		}
718a18c35b9SAndreas Jaekel 		if (ret == 0)
719a18c35b9SAndreas Jaekel 			continue;
720d979f56cSAndreas Jaekel 		while (ret > off) {
721d979f56cSAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
722d979f56cSAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
723d979f56cSAndreas Jaekel 			off += ev->header.record_len;
724d979f56cSAndreas Jaekel 		}
725149d0affSAndreas Jaekel 		off = 0;
726a18c35b9SAndreas Jaekel 	}
7276a6a51eeSAndreas Jaekel 	if (create_tmp_queue)
728add9520fSAndreas Jaekel 		close(q_fd);
729add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
730a18c35b9SAndreas Jaekel }
731a18c35b9SAndreas Jaekel 
73235526fb3SArne Jansen static int
zev_dump_spool(int fd)73335526fb3SArne Jansen zev_dump_spool(int fd)
73435526fb3SArne Jansen {
73535526fb3SArne Jansen 	int len;
73635526fb3SArne Jansen 	char buf[4096];
73735526fb3SArne Jansen 	int off = 0;
73835526fb3SArne Jansen 
73935526fb3SArne Jansen 	while (1) {
74035526fb3SArne Jansen 		len = read(fd, buf + off, sizeof(buf) - off);
74135526fb3SArne Jansen 		if (len == -1) {
74235526fb3SArne Jansen 			fprintf(stderr, "reading from spool failed: %s\n",
74335526fb3SArne Jansen 				strerror(errno));
74435526fb3SArne Jansen 			return EXIT_FAILURE;
74535526fb3SArne Jansen 		}
74635526fb3SArne Jansen 		if (len == 0)
74735526fb3SArne Jansen 			break;
74835526fb3SArne Jansen 
74935526fb3SArne Jansen 		len += off;
75035526fb3SArne Jansen 		off = 0;
75135526fb3SArne Jansen 		while (len > off + sizeof(uint32_t)) {
75235526fb3SArne Jansen 			uint32_t evlen;
75335526fb3SArne Jansen 			char *mp;
75435526fb3SArne Jansen 			zev_event_t *ev;
75535526fb3SArne Jansen 
75635526fb3SArne Jansen 			ev = (zev_event_t *)(buf + off);
75735526fb3SArne Jansen 			evlen = ev->header.record_len;
75835526fb3SArne Jansen 			if (len < off + evlen + 1)
75935526fb3SArne Jansen 				break;
76035526fb3SArne Jansen 			mp = buf + off + evlen;
76135526fb3SArne Jansen 			if (!memchr(mp, 0, len - off - evlen))
76235526fb3SArne Jansen 				break;
76335526fb3SArne Jansen 			zev_print_event(buf + off, ev->header.record_len);
76435526fb3SArne Jansen 			off += ev->header.record_len + strlen(mp) + 1;
76535526fb3SArne Jansen 		}
76635526fb3SArne Jansen 
76735526fb3SArne Jansen 		memmove(buf, buf + off, len - off);
76835526fb3SArne Jansen 		off = len - off;
76935526fb3SArne Jansen 	}
77035526fb3SArne Jansen 
77135526fb3SArne Jansen 	return EXIT_SUCCESS;
77235526fb3SArne Jansen }
77335526fb3SArne Jansen 
774a18c35b9SAndreas Jaekel static void
usage(char * progname)775a18c35b9SAndreas Jaekel usage(char *progname)
776a18c35b9SAndreas Jaekel {
777add9520fSAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
778add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
779add9520fSAndreas Jaekel 	fprintf(stderr, " Status information:\n");
780a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
781a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
78235526fb3SArne Jansen 	fprintf(stderr, "   -f <name>            dump events from spool\n");
783add9520fSAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
784add9520fSAndreas Jaekel 	        "information\n");
785b690436dSAndreas Jaekel 	fprintf(stderr, "   -T <interval> <cnt>  zevstat mode\n");
786f432e238SAndreas Jaekel 	fprintf(stderr, "   -R <base filename>   zevreport mode\n");
787add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
788add9520fSAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
789add9520fSAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
790add9520fSAndreas Jaekel 	        "length\n");
791add9520fSAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
792add9520fSAndreas Jaekel 	        "this pool\n");
793a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
794add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
795add9520fSAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
796add9520fSAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
7976a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
7986a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
799add9520fSAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
800add9520fSAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
801add9520fSAndreas Jaekel 	        "(default)\n");
802add9520fSAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
803add9520fSAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
8046a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
805add9520fSAndreas Jaekel 	        "length\n");
806add9520fSAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
807add9520fSAndreas Jaekel 	        "throttle\n");
808add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
809add9520fSAndreas Jaekel 	fprintf(stderr, " Other options:\n");
810add9520fSAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
811add9520fSAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
8126a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
8136a6a51eeSAndreas Jaekel 		"queue name\n");
814888fea18SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
81542110aacSAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
81642110aacSAndreas Jaekel 		"checksums\n");
81716ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
818205ed6bfSAndreas Jaekel 	        "for some operations\n");
81916ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
82016ff6b2fSAndreas Jaekel 	        "one event per line\n");
821*8cfb36b9SArne Jansen 	fprintf(stderr, "   -G <guid>            filter event output by guid, "
822*8cfb36b9SArne Jansen 		"can be given more than once\n");
823e3455c18SAndreas Jaekel 	fprintf(stderr, "   -V                   query zev module version\n");
824342055d2SArne Jansen 	fprintf(stderr, "   -F                   flush output after each line\n");
825a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
826a18c35b9SAndreas Jaekel }
827a18c35b9SAndreas Jaekel 
82850da9edeSAndreas Jaekel static void
zevstat_usage(char * progname)82950da9edeSAndreas Jaekel zevstat_usage(char *progname)
83050da9edeSAndreas Jaekel {
83150da9edeSAndreas Jaekel 	fprintf(stderr, "usage: %s [-v] <interval> [count]\n", progname);
83250da9edeSAndreas Jaekel 	fprintf(stderr, "   -v   verbose, show counters for all event types\n");
83350da9edeSAndreas Jaekel 	exit (EXIT_FAILURE);
83450da9edeSAndreas Jaekel }
83550da9edeSAndreas Jaekel 
836f432e238SAndreas Jaekel static void
zevreport_usage(char * progname)837f432e238SAndreas Jaekel zevreport_usage(char *progname)
838f432e238SAndreas Jaekel {
839f432e238SAndreas Jaekel 	fprintf(stderr, "usage: %s <output base filename>\n", progname);
840f432e238SAndreas Jaekel 	exit (EXIT_FAILURE);
841f432e238SAndreas Jaekel }
842f432e238SAndreas Jaekel 
843a18c35b9SAndreas Jaekel static int
zev_add_queue(int fd,char * arg,int blocking)8446a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
845a18c35b9SAndreas Jaekel {
846add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
847add9520fSAndreas Jaekel 	int namelen;
848a18c35b9SAndreas Jaekel 
849add9520fSAndreas Jaekel 	namelen = strlen(arg);
850add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
851add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
852a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
853a18c35b9SAndreas Jaekel 	}
854add9520fSAndreas Jaekel 
855add9520fSAndreas Jaekel 	aq.zev_namelen = namelen;
856add9520fSAndreas Jaekel 	strcpy(aq.zev_name, arg);
857c99a1a25SAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT | ZEV_FL_INITIALLY_EMPTY;
8586a6a51eeSAndreas Jaekel 	if (blocking) {
8596a6a51eeSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
8606a6a51eeSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
8616a6a51eeSAndreas Jaekel 	} else {
862add9520fSAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
8636a6a51eeSAndreas Jaekel 	}
864add9520fSAndreas Jaekel 
865add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
866add9520fSAndreas Jaekel 		perror("adding queue failed");
867a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
868a18c35b9SAndreas Jaekel 	}
869a18c35b9SAndreas Jaekel 	return (0);
870a18c35b9SAndreas Jaekel }
871a18c35b9SAndreas Jaekel 
872a18c35b9SAndreas Jaekel static int
zev_remove_queue(int fd,char * arg)873add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg)
874fec460f8SAndreas Jaekel {
875add9520fSAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
876add9520fSAndreas Jaekel 	int namelen;
877fec460f8SAndreas Jaekel 
878add9520fSAndreas Jaekel 	namelen = strlen(arg);
879add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
880add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
881fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
882fec460f8SAndreas Jaekel 	}
883add9520fSAndreas Jaekel 
8846a6a51eeSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
8856a6a51eeSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
886add9520fSAndreas Jaekel 
887add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
888add9520fSAndreas Jaekel 		perror("removing queue failed");
889add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
890add9520fSAndreas Jaekel 	}
891add9520fSAndreas Jaekel 	return (0);
892add9520fSAndreas Jaekel }
893add9520fSAndreas Jaekel 
894add9520fSAndreas Jaekel static int
zev_set_global_max_queue_len(int fd,char * arg)895add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
896add9520fSAndreas Jaekel {
897add9520fSAndreas Jaekel 	uint64_t maxqueuelen;
898add9520fSAndreas Jaekel 
899174dc952SAndreas Jaekel 	if (!arg) {
900174dc952SAndreas Jaekel 		fprintf(stderr, "missing queue length parameter\n");
901174dc952SAndreas Jaekel 		return (EXIT_FAILURE);
902174dc952SAndreas Jaekel 	}
903174dc952SAndreas Jaekel 
904add9520fSAndreas Jaekel 	errno = 0;
905add9520fSAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
906add9520fSAndreas Jaekel 	if (errno) {
907add9520fSAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
908add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
909add9520fSAndreas Jaekel 	}
910add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
911add9520fSAndreas Jaekel 		perror("setting max queue length failed");
912fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
913fec460f8SAndreas Jaekel 	}
914fec460f8SAndreas Jaekel 	return (0);
915fec460f8SAndreas Jaekel }
916fec460f8SAndreas Jaekel 
917fec460f8SAndreas Jaekel static int
zev_mute_unmute_impl(int fd,char * poolname,int mute)918a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
919a18c35b9SAndreas Jaekel {
920a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
921a18c35b9SAndreas Jaekel 	int len;
922a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
923a18c35b9SAndreas Jaekel 	len = strlen(poolname);
924a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
925a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
926a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
927a18c35b9SAndreas Jaekel 	}
928a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
929a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
930a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
931a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
932a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
933a18c35b9SAndreas Jaekel 	}
934a18c35b9SAndreas Jaekel 	return (0);
935a18c35b9SAndreas Jaekel }
936a18c35b9SAndreas Jaekel 
937a18c35b9SAndreas Jaekel int
zev_mute_pool(int fd,char * poolname)938a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
939a18c35b9SAndreas Jaekel {
940a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
941a18c35b9SAndreas Jaekel }
942a18c35b9SAndreas Jaekel 
943a18c35b9SAndreas Jaekel int
zev_unmute_pool(int fd,char * poolname)944a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
945a18c35b9SAndreas Jaekel {
946a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
947a18c35b9SAndreas Jaekel }
948a18c35b9SAndreas Jaekel 
949888fea18SAndreas Jaekel static int
zev_debug_info(int fd)950add9520fSAndreas Jaekel zev_debug_info(int fd)
951add9520fSAndreas Jaekel {
952add9520fSAndreas Jaekel 	zev_ioctl_debug_info_t di;
953add9520fSAndreas Jaekel 
954add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
955add9520fSAndreas Jaekel 		perror("getting zev debug info failed");
956add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
957add9520fSAndreas Jaekel 	}
958add9520fSAndreas Jaekel 
959add9520fSAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
960205ed6bfSAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
961205ed6bfSAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
962205ed6bfSAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
963add9520fSAndreas Jaekel 	return 0;
964add9520fSAndreas Jaekel }
965add9520fSAndreas Jaekel 
966add9520fSAndreas Jaekel static int
zev_mark(int fd,char * arg)967888fea18SAndreas Jaekel zev_mark(int fd, char *arg)
968888fea18SAndreas Jaekel {
969888fea18SAndreas Jaekel 	zev_ioctl_mark_t *mark;
970888fea18SAndreas Jaekel 	uint64_t guid;
971888fea18SAndreas Jaekel 	int len;
972888fea18SAndreas Jaekel 	char *p;
973888fea18SAndreas Jaekel 
974888fea18SAndreas Jaekel 	p = strchr(arg, ':');
975888fea18SAndreas Jaekel 	if (!p) {
976888fea18SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
977888fea18SAndreas Jaekel 		        "e.g. '123:hello'\n");
978888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
979888fea18SAndreas Jaekel 	}
980888fea18SAndreas Jaekel 	*p = '\n';
981888fea18SAndreas Jaekel 	p++;
982888fea18SAndreas Jaekel 
983888fea18SAndreas Jaekel 	errno = 0;
984add9520fSAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
985888fea18SAndreas Jaekel 	if (errno) {
986888fea18SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
987888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
988888fea18SAndreas Jaekel 	}
989888fea18SAndreas Jaekel 
990888fea18SAndreas Jaekel 	len = strlen(p);
991888fea18SAndreas Jaekel 
992888fea18SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
993888fea18SAndreas Jaekel 	if (!mark) {
994888fea18SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
995888fea18SAndreas Jaekel 		        strerror(errno));
996888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
997888fea18SAndreas Jaekel 	}
998888fea18SAndreas Jaekel 	mark->zev_guid = guid;
999888fea18SAndreas Jaekel 	mark->zev_mark_id = 0;
1000888fea18SAndreas Jaekel 	mark->zev_payload_len = len;
1001888fea18SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
1002888fea18SAndreas Jaekel 
1003888fea18SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
1004888fea18SAndreas Jaekel 		perror("queueing mark failed");
1005888fea18SAndreas Jaekel 		return (EXIT_FAILURE);
1006888fea18SAndreas Jaekel 	}
1007888fea18SAndreas Jaekel 
1008888fea18SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
1009888fea18SAndreas Jaekel 	return (0);
1010888fea18SAndreas Jaekel }
1011888fea18SAndreas Jaekel 
1012add9520fSAndreas Jaekel static int
zev_queue_blocking(int fd,char * arg,int block)1013add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
1014add9520fSAndreas Jaekel {
1015add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1016add9520fSAndreas Jaekel 
10176a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10186a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1019add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1020add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1021add9520fSAndreas Jaekel 	}
10226a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1023add9520fSAndreas Jaekel 
1024add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1025add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1026add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1027add9520fSAndreas Jaekel 	}
1028add9520fSAndreas Jaekel 	if (block) {
1029add9520fSAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
1030add9520fSAndreas Jaekel 	} else {
1031add9520fSAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
1032add9520fSAndreas Jaekel 	}
1033add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1034add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1035add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1036add9520fSAndreas Jaekel 	}
1037add9520fSAndreas Jaekel 	return (0);
1038add9520fSAndreas Jaekel }
1039add9520fSAndreas Jaekel 
1040add9520fSAndreas Jaekel static int
zev_set_max_queue_len(int fd,char * arg,char * len)1041add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
1042add9520fSAndreas Jaekel {
1043add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1044add9520fSAndreas Jaekel 
1045add9520fSAndreas Jaekel 	if (!len) {
1046add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
1047add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1048add9520fSAndreas Jaekel 	}
1049add9520fSAndreas Jaekel 
10506a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10516a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1052add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1053add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1054add9520fSAndreas Jaekel 	}
10556a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1056add9520fSAndreas Jaekel 
1057add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1058add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1059add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1060add9520fSAndreas Jaekel 	}
1061add9520fSAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
1062add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
1063add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
1064add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1065add9520fSAndreas Jaekel 	}
1066add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
1067add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
1068add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1069add9520fSAndreas Jaekel 	}
1070add9520fSAndreas Jaekel 
1071add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1072add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1073add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1074add9520fSAndreas Jaekel 	}
1075add9520fSAndreas Jaekel 	return (0);
1076add9520fSAndreas Jaekel }
1077add9520fSAndreas Jaekel 
1078add9520fSAndreas Jaekel static int
zev_set_poll_wakeup_queue_len(int fd,char * arg,char * len)1079add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
1080add9520fSAndreas Jaekel {
1081add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1082add9520fSAndreas Jaekel 
1083add9520fSAndreas Jaekel 	if (!len) {
1084add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
1085add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1086add9520fSAndreas Jaekel 	}
1087add9520fSAndreas Jaekel 
10886a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10896a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1090add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1091add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1092add9520fSAndreas Jaekel 	}
10936a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1094add9520fSAndreas Jaekel 
1095add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1096add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1097add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1098add9520fSAndreas Jaekel 	}
1099add9520fSAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
1100add9520fSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
1101add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
1102add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1103add9520fSAndreas Jaekel 	}
11046a6a51eeSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
1105add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
1106add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1107add9520fSAndreas Jaekel 	}
1108add9520fSAndreas Jaekel 
1109add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
1110add9520fSAndreas Jaekel 		perror("setting queue properties failed");
1111add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1112add9520fSAndreas Jaekel 	}
1113add9520fSAndreas Jaekel 	return (0);
1114add9520fSAndreas Jaekel }
1115add9520fSAndreas Jaekel 
1116add9520fSAndreas Jaekel static int
zev_queue_properties(int fd,char * arg)1117add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg)
1118add9520fSAndreas Jaekel {
1119add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1120add9520fSAndreas Jaekel 
11216a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
11226a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1123add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1124add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1125add9520fSAndreas Jaekel 	}
11266a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1127add9520fSAndreas Jaekel 
1128add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1129add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1130add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1131add9520fSAndreas Jaekel 	}
1132add9520fSAndreas Jaekel 
1133add9520fSAndreas Jaekel 	printf("queue        : %s\n", arg);
1134add9520fSAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1135add9520fSAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1136add9520fSAndreas Jaekel 	printf("persistent   : %s\n",
1137add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1138add9520fSAndreas Jaekel 	printf("blocking     : %s\n",
1139add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1140add9520fSAndreas Jaekel 
1141add9520fSAndreas Jaekel 	return (0);
1142add9520fSAndreas Jaekel }
1143add9520fSAndreas Jaekel 
1144add9520fSAndreas Jaekel static int
zev_list_queues(int fd)1145add9520fSAndreas Jaekel zev_list_queues(int fd)
1146add9520fSAndreas Jaekel {
1147add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1148add9520fSAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1149add9520fSAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1150add9520fSAndreas Jaekel 	uint64_t	i;
1151add9520fSAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
115293bacbbdSAndreas Jaekel 	zev_statistics_t zs;
115393bacbbdSAndreas Jaekel 
115493bacbbdSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
115593bacbbdSAndreas Jaekel 		perror("getting statistics data failed");
115693bacbbdSAndreas Jaekel 		return (EXIT_FAILURE);
115793bacbbdSAndreas Jaekel 	}
1158add9520fSAndreas Jaekel 
1159add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1160add9520fSAndreas Jaekel 		perror("getting queue list failed");
1161add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1162add9520fSAndreas Jaekel 	}
1163add9520fSAndreas Jaekel 
1164add9520fSAndreas Jaekel 	printf("Name                                     Size       "
116593bacbbdSAndreas Jaekel 	       "Size%% Max Size   Per Block\n");
1166add9520fSAndreas Jaekel 
1167add9520fSAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1168add9520fSAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1169add9520fSAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1170add9520fSAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1171add9520fSAndreas Jaekel 
11726a6a51eeSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
11736a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11746a6a51eeSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
11756a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1176add9520fSAndreas Jaekel 
1177add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1178add9520fSAndreas Jaekel 			if (errno == ENOENT)
1179add9520fSAndreas Jaekel 				continue;
1180add9520fSAndreas Jaekel 			perror("getting queue properties failed");
1181add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1182add9520fSAndreas Jaekel 		}
1183add9520fSAndreas Jaekel 
11846a6a51eeSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
11856a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
11866a6a51eeSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
11876a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1188add9520fSAndreas Jaekel 
1189add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1190add9520fSAndreas Jaekel 			if (errno == ENOENT)
1191add9520fSAndreas Jaekel 				continue;
1192add9520fSAndreas Jaekel 			perror("getting statistics data failed");
1193add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1194add9520fSAndreas Jaekel 		}
1195add9520fSAndreas Jaekel 
119693bacbbdSAndreas Jaekel 		if (gqp.zev_max_queue_len == 0) {
119793bacbbdSAndreas Jaekel 			gqp.zev_max_queue_len = zs.zev_max_queue_len;
119893bacbbdSAndreas Jaekel 		}
119993bacbbdSAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %5.1f %-10" PRIu64
1200add9520fSAndreas Jaekel 		       " %-3s %-3s\n",
1201add9520fSAndreas Jaekel 			name,
120293bacbbdSAndreas Jaekel 			gs.zev_statistics.zev_queue_len * 100.0 /
120393bacbbdSAndreas Jaekel 				gqp.zev_max_queue_len,
1204add9520fSAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1205add9520fSAndreas Jaekel 			gqp.zev_max_queue_len,
1206add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1207add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1208add9520fSAndreas Jaekel 				 "yes" : "no");
1209add9520fSAndreas Jaekel 	}
1210add9520fSAndreas Jaekel 
1211add9520fSAndreas Jaekel 	return (0);
1212add9520fSAndreas Jaekel }
1213add9520fSAndreas Jaekel 
121442110aacSAndreas Jaekel static int
zev_checksum(int dev_fd,char * filename)121542110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename)
121642110aacSAndreas Jaekel {
121742110aacSAndreas Jaekel 	int fd;
121842110aacSAndreas Jaekel 	offset_t off;
121942110aacSAndreas Jaekel 	offset_t data;
122042110aacSAndreas Jaekel 	zev_sig_t *sig;
122142110aacSAndreas Jaekel 	char *buf;
122242110aacSAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
122342110aacSAndreas Jaekel 	int i;
122442110aacSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
122542110aacSAndreas Jaekel 	int buf_size;
122642110aacSAndreas Jaekel 
122742110aacSAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
122842110aacSAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
122942110aacSAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
123042110aacSAndreas Jaekel 	if (!buf) {
123142110aacSAndreas Jaekel 		perror("can't allocate checksum buffer");
123242110aacSAndreas Jaekel 		return (EXIT_FAILURE);
123342110aacSAndreas Jaekel 	}
123442110aacSAndreas Jaekel 
123542110aacSAndreas Jaekel 	fd = open(filename, O_RDONLY);
123642110aacSAndreas Jaekel 	if (fd < 0) {
123742110aacSAndreas Jaekel 		perror("can't open file");
123842110aacSAndreas Jaekel 		return (EXIT_FAILURE);
123942110aacSAndreas Jaekel 	}
124042110aacSAndreas Jaekel 
124142110aacSAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
124242110aacSAndreas Jaekel 	gs->zev_fd = fd;
124342110aacSAndreas Jaekel 	gs->zev_bufsize = buf_size;
124442110aacSAndreas Jaekel 
124542110aacSAndreas Jaekel 	off = 0;
124642110aacSAndreas Jaekel 	data = 0;
124742110aacSAndreas Jaekel 	while (1) {
124842110aacSAndreas Jaekel 		errno = 0;
124942110aacSAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
125042110aacSAndreas Jaekel 		if (data < 0) {
125142110aacSAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
125242110aacSAndreas Jaekel 				break;
125342110aacSAndreas Jaekel 			perror("llseek failed");
125442110aacSAndreas Jaekel 			goto err;
125542110aacSAndreas Jaekel 		}
125642110aacSAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
125742110aacSAndreas Jaekel 		off = data + ZEV_L1_SIZE;
125842110aacSAndreas Jaekel 
125942110aacSAndreas Jaekel 		gs->zev_offset = data;
126042110aacSAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
126142110aacSAndreas Jaekel 
126242110aacSAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
126342110aacSAndreas Jaekel 			perror("ioctl to get signatures failed");
126442110aacSAndreas Jaekel 			goto err;
126542110aacSAndreas Jaekel 		}
126642110aacSAndreas Jaekel 
126742110aacSAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
126842110aacSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
126942110aacSAndreas Jaekel 			sig += i;
127042110aacSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
127142110aacSAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
127242110aacSAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
127342110aacSAndreas Jaekel 		}
127442110aacSAndreas Jaekel 	}
127542110aacSAndreas Jaekel 
127642110aacSAndreas Jaekel 	free(buf);
127742110aacSAndreas Jaekel 	close(fd);
127842110aacSAndreas Jaekel 	return 0;
127942110aacSAndreas Jaekel err:
128042110aacSAndreas Jaekel 	free(buf);
128142110aacSAndreas Jaekel 	close(fd);
128242110aacSAndreas Jaekel 	return (EXIT_FAILURE);
128342110aacSAndreas Jaekel }
128442110aacSAndreas Jaekel 
1285b690436dSAndreas Jaekel typedef struct zevstat {
1286b690436dSAndreas Jaekel 	uint64_t	ns_start;
1287b690436dSAndreas Jaekel 	uint64_t	events[ZEV_OP_MIN + ZEV_OP_MAX];
1288b690436dSAndreas Jaekel 	uint64_t	guids;
1289b690436dSAndreas Jaekel 	uint64_t	total_events;
1290b690436dSAndreas Jaekel 	uint64_t	total_guids;
1291b690436dSAndreas Jaekel 	avl_tree_t	guids_interval;
1292b690436dSAndreas Jaekel 	avl_tree_t	guids_runtime;
1293b690436dSAndreas Jaekel } zevstat_t;
1294b690436dSAndreas Jaekel 
1295b690436dSAndreas Jaekel typedef struct zev_guidtrack_t {
1296b690436dSAndreas Jaekel 	uint64_t	guid;
1297b690436dSAndreas Jaekel 	avl_node_t	avl_interval;
1298b690436dSAndreas Jaekel 	avl_node_t	avl_runtime;
1299b690436dSAndreas Jaekel } zev_guidtrack_t;
1300b690436dSAndreas Jaekel 
1301b690436dSAndreas Jaekel zevstat_t zevstat;
1302b690436dSAndreas Jaekel 
1303b690436dSAndreas Jaekel static void
zev_eventstat(char * buf,int len)1304b690436dSAndreas Jaekel zev_eventstat(char *buf, int len)
1305b690436dSAndreas Jaekel {
1306b690436dSAndreas Jaekel 	zev_header_t *rec = (zev_header_t *)buf;
1307b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1308b690436dSAndreas Jaekel 	zev_guidtrack_t *gt_int;
1309b690436dSAndreas Jaekel 	zev_guidtrack_t to_find;
1310b690436dSAndreas Jaekel 	avl_index_t where;
1311b690436dSAndreas Jaekel 
1312b690436dSAndreas Jaekel 	zevstat.total_events++;
1313b690436dSAndreas Jaekel 	zevstat.events[rec->op]++;
1314b690436dSAndreas Jaekel 
1315b690436dSAndreas Jaekel 	to_find.guid = rec->guid;
1316b690436dSAndreas Jaekel 	gt = avl_find(&zevstat.guids_runtime, &to_find, &where);
1317b690436dSAndreas Jaekel 	if (!gt) {
1318b690436dSAndreas Jaekel 		gt = malloc(sizeof(*gt));
1319b690436dSAndreas Jaekel 		if (!gt) {
1320b690436dSAndreas Jaekel 			perror("can't get guid tracking record");
1321b690436dSAndreas Jaekel 			exit (EXIT_FAILURE);
1322b690436dSAndreas Jaekel 		}
1323b690436dSAndreas Jaekel 		gt->guid = rec->guid;
1324b690436dSAndreas Jaekel 		avl_insert(&zevstat.guids_runtime, gt, where);
1325b690436dSAndreas Jaekel 	}
1326b690436dSAndreas Jaekel 	gt_int = avl_find(&zevstat.guids_interval, &to_find, &where);
1327b690436dSAndreas Jaekel 	if (!gt_int)
1328b690436dSAndreas Jaekel 		avl_insert(&zevstat.guids_interval, gt, where);
1329b690436dSAndreas Jaekel }
1330b690436dSAndreas Jaekel 
1331b690436dSAndreas Jaekel static void
zev_eventstat_interval(FILE * out)1332f432e238SAndreas Jaekel zev_eventstat_interval(FILE *out)
1333b690436dSAndreas Jaekel {
1334b690436dSAndreas Jaekel 	uint64_t events;
1335b690436dSAndreas Jaekel 	int i;
1336b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1337b690436dSAndreas Jaekel 
1338b690436dSAndreas Jaekel 	events = 0;
1339b690436dSAndreas Jaekel 	for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++) {
1340b690436dSAndreas Jaekel 		events += zevstat.events[i];
1341b690436dSAndreas Jaekel 	}
1342b690436dSAndreas Jaekel 
1343b690436dSAndreas Jaekel 	if (verbose) {
1344f432e238SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu  ",
1345b690436dSAndreas Jaekel 		        time(NULL),
1346b690436dSAndreas Jaekel 		        events,
1347b690436dSAndreas Jaekel 		        zevstat.total_events,
1348b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
1349b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
1350b690436dSAndreas Jaekel 		for (i = ZEV_OP_MIN; i <= ZEV_OP_MAX; i++)
1351f432e238SAndreas Jaekel 			fprintf(out, "%6llu ", zevstat.events[i]);
1352f432e238SAndreas Jaekel 		fprintf(out, "\n");
1353b690436dSAndreas Jaekel 	} else {
1354f432e238SAndreas Jaekel 		fprintf(out, "%u  %6llu  %6llu %6llu %6llu\n",
1355b690436dSAndreas Jaekel 		        time(NULL),
1356b690436dSAndreas Jaekel 		        events,
1357b690436dSAndreas Jaekel 		        zevstat.total_events,
1358b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_interval),
1359b690436dSAndreas Jaekel 		        avl_numnodes(&zevstat.guids_runtime));
1360b690436dSAndreas Jaekel 	}
1361b690436dSAndreas Jaekel 	memset(&zevstat.events, 0, sizeof(zevstat.events));
1362b690436dSAndreas Jaekel 	zevstat.guids = 0;
1363b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
1364b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
1365f432e238SAndreas Jaekel 	fflush(out);
1366b690436dSAndreas Jaekel }
1367b690436dSAndreas Jaekel 
1368b690436dSAndreas Jaekel static int
zev_evcompar(const void * a,const void * b)1369b690436dSAndreas Jaekel zev_evcompar(const void *a, const void *b)
1370b690436dSAndreas Jaekel {
1371b690436dSAndreas Jaekel 	const zev_guidtrack_t *ga = a;
1372b690436dSAndreas Jaekel 	const zev_guidtrack_t *gb = b;
1373b690436dSAndreas Jaekel 
1374b690436dSAndreas Jaekel 	if (ga->guid > gb->guid)
1375b690436dSAndreas Jaekel 		return 1;
1376b690436dSAndreas Jaekel 	if (ga->guid < gb->guid)
1377b690436dSAndreas Jaekel 		return -1;
1378b690436dSAndreas Jaekel 	return 0;
1379b690436dSAndreas Jaekel }
1380b690436dSAndreas Jaekel 
1381b690436dSAndreas Jaekel static int
zev_zevstat(int fd,char * s_interval,char * s_count,char * outfile)1382f432e238SAndreas Jaekel zev_zevstat(int fd, char *s_interval, char *s_count, char *outfile)
1383b690436dSAndreas Jaekel {
1384b690436dSAndreas Jaekel 	uint64_t interval = 1000;
1385b690436dSAndreas Jaekel 	uint64_t ms;
1386b690436dSAndreas Jaekel 	uint64_t t_until;
1387b690436dSAndreas Jaekel 	uint64_t t_now;
1388b690436dSAndreas Jaekel 	int cnt = -1;
1389b690436dSAndreas Jaekel 	struct pollfd pfd[1];
1390b690436dSAndreas Jaekel 	int ret;
1391b690436dSAndreas Jaekel 	char buf[4096];
1392b690436dSAndreas Jaekel 	zev_event_t *ev;
1393b690436dSAndreas Jaekel 	int off = 0;
1394b690436dSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
1395b690436dSAndreas Jaekel 	int q_fd;
1396b690436dSAndreas Jaekel 	zev_guidtrack_t *gt;
1397f432e238SAndreas Jaekel 	FILE *out = stdout;
1398f432e238SAndreas Jaekel 	struct stat st;
1399f432e238SAndreas Jaekel 	char filename[MAXPATHLEN];
1400f432e238SAndreas Jaekel 	int retry;
1401f432e238SAndreas Jaekel 
1402f432e238SAndreas Jaekel 	if (outfile) {
1403f432e238SAndreas Jaekel 		retry = 0;
1404f432e238SAndreas Jaekel 		strncpy(filename, outfile, sizeof(filename));
1405f432e238SAndreas Jaekel 		while (stat(filename, &st) == 0) {
1406f432e238SAndreas Jaekel 			/* file exists */
1407f432e238SAndreas Jaekel 			snprintf(filename, sizeof(filename),
1408f432e238SAndreas Jaekel 			         "%s.%d", outfile, retry);
1409f432e238SAndreas Jaekel 			retry++;
1410f432e238SAndreas Jaekel 		}
1411f432e238SAndreas Jaekel 		out = fopen(filename, "wb+");
1412f432e238SAndreas Jaekel 		if (!out) {
1413f432e238SAndreas Jaekel 			perror("opening output file failed");
1414f432e238SAndreas Jaekel 			return (EXIT_FAILURE);
1415f432e238SAndreas Jaekel 		}
1416f432e238SAndreas Jaekel 	}
1417b690436dSAndreas Jaekel 
1418b690436dSAndreas Jaekel 	memset(&zevstat, 0, sizeof(zevstat));
1419b690436dSAndreas Jaekel 	avl_create(&zevstat.guids_runtime, zev_evcompar,
1420b690436dSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
1421b690436dSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_runtime));
1422b690436dSAndreas Jaekel 	avl_create(&zevstat.guids_interval, zev_evcompar,
1423b690436dSAndreas Jaekel 	           sizeof(zev_guidtrack_t),
1424b690436dSAndreas Jaekel 	           offsetof(zev_guidtrack_t, avl_interval));
1425b690436dSAndreas Jaekel 
142619695134SAndreas Jaekel 	if (s_interval) {
1427b690436dSAndreas Jaekel 		interval = atol(s_interval);
1428b690436dSAndreas Jaekel 		if (interval == 0) {
1429b690436dSAndreas Jaekel 			fprintf(stderr, "invalid interval.\n");
1430b690436dSAndreas Jaekel 			return (EXIT_FAILURE);
1431b690436dSAndreas Jaekel 		}
1432b690436dSAndreas Jaekel 		interval *= 1000;
143319695134SAndreas Jaekel 	}
1434b690436dSAndreas Jaekel 	if (s_count) {
1435b690436dSAndreas Jaekel 		cnt = atol(s_count);
1436b690436dSAndreas Jaekel 		if (interval == 0) {
1437b690436dSAndreas Jaekel 			fprintf(stderr, "invalid count.\n");
1438b690436dSAndreas Jaekel 			return (EXIT_FAILURE);
1439b690436dSAndreas Jaekel 		}
1440b690436dSAndreas Jaekel 	}
1441b690436dSAndreas Jaekel 
1442b690436dSAndreas Jaekel 	aq.zev_max_queue_len = 1024 * 1024;
1443c99a1a25SAndreas Jaekel 	aq.zev_flags = ZEV_FL_INITIALLY_EMPTY;
1444b690436dSAndreas Jaekel 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
1445b690436dSAndreas Jaekel 		 "zevstat.%ld.%ld", time(NULL), getpid());
1446b690436dSAndreas Jaekel 	aq.zev_namelen = strlen(aq.zev_name);
1447b690436dSAndreas Jaekel 
1448b690436dSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
1449b690436dSAndreas Jaekel 		perror("adding temporary queue failed");
1450b690436dSAndreas Jaekel 		return (EXIT_FAILURE);
1451b690436dSAndreas Jaekel 	}
1452b690436dSAndreas Jaekel 
1453b690436dSAndreas Jaekel 	snprintf(buf, sizeof(buf),
1454b690436dSAndreas Jaekel 		 "/devices/pseudo/zev@0:%s", aq.zev_name);
1455b690436dSAndreas Jaekel 	q_fd = open(buf, O_RDONLY);
1456b690436dSAndreas Jaekel 	if (q_fd < 0) {
1457b690436dSAndreas Jaekel 		perror("opening queue device failed");
1458b690436dSAndreas Jaekel 		return (EXIT_FAILURE);
1459b690436dSAndreas Jaekel 	}
1460b690436dSAndreas Jaekel 
1461b690436dSAndreas Jaekel 	pfd[0].fd = q_fd;
1462b690436dSAndreas Jaekel 	pfd[0].events = POLLIN;
1463b690436dSAndreas Jaekel 
1464b690436dSAndreas Jaekel 	/* drain queue */
146519695134SAndreas Jaekel 	while ((ret = poll(pfd, 1, 0)) > 0) {
1466b690436dSAndreas Jaekel 		if (read(q_fd, buf, sizeof(buf)) < 0) {
1467b690436dSAndreas Jaekel 			perror("read failed");
1468b690436dSAndreas Jaekel 			close(q_fd);
1469b690436dSAndreas Jaekel 			return(EXIT_FAILURE);
1470b690436dSAndreas Jaekel 		}
1471b690436dSAndreas Jaekel 	}
1472b690436dSAndreas Jaekel 	if (ret < 0) {
1473b690436dSAndreas Jaekel 		perror("poll failed");
1474b690436dSAndreas Jaekel 		close(q_fd);
1475b690436dSAndreas Jaekel 		return(EXIT_FAILURE);
1476b690436dSAndreas Jaekel 	}
1477b690436dSAndreas Jaekel 
1478f432e238SAndreas Jaekel 	fprintf(out, "timestamp   events tevents  guids tguids");
1479b690436dSAndreas Jaekel 	if (verbose) {
1480f432e238SAndreas Jaekel 		fprintf(out, "   error   mark  mount umount zvol_w ");
1481f432e238SAndreas Jaekel 		fprintf(out, "zvol_t  close create  mkdir mxattr ");
1482f432e238SAndreas Jaekel 		fprintf(out, "remove  rmdir   link symlnk rename  ");
1483f432e238SAndreas Jaekel 		fprintf(out, "write  trunc setatt    acl");
1484b690436dSAndreas Jaekel 	}
1485f432e238SAndreas Jaekel 	fprintf(out, "\n");
1486b690436dSAndreas Jaekel 	while (cnt) {
1487b690436dSAndreas Jaekel 		t_until = gethrtime() + (interval * 1000000);
1488b690436dSAndreas Jaekel 		ms = interval;
1489b690436dSAndreas Jaekel 		do {
1490b690436dSAndreas Jaekel 			ret = poll(pfd, 1, ms);
1491b690436dSAndreas Jaekel 			t_now = gethrtime();
1492b690436dSAndreas Jaekel 			if (t_now < t_until) {
1493b690436dSAndreas Jaekel 				ms = t_until - t_now;
1494b690436dSAndreas Jaekel 				ms /= 1000000ull;
1495b690436dSAndreas Jaekel 			}
1496b690436dSAndreas Jaekel 			if (ret < 0) {
1497b690436dSAndreas Jaekel 				perror("poll failed");
1498b690436dSAndreas Jaekel 				close(q_fd);
1499b690436dSAndreas Jaekel 				return(EXIT_FAILURE);
1500b690436dSAndreas Jaekel 			}
1501b690436dSAndreas Jaekel 			if (!(pfd[0].revents & POLLIN))
1502b690436dSAndreas Jaekel 				continue;
1503b690436dSAndreas Jaekel 			/* data available */
1504b690436dSAndreas Jaekel 			ret = read(q_fd, buf, sizeof(buf));
1505b690436dSAndreas Jaekel 			if (ret < 0) {
1506b690436dSAndreas Jaekel 				perror("read failed");
1507b690436dSAndreas Jaekel 				close(q_fd);
1508b690436dSAndreas Jaekel 				return(EXIT_FAILURE);
1509b690436dSAndreas Jaekel 			}
1510b690436dSAndreas Jaekel 			if (ret == 0)
1511b690436dSAndreas Jaekel 				continue;
1512b690436dSAndreas Jaekel 			while (ret > off) {
1513b690436dSAndreas Jaekel 				ev = (zev_event_t *)(buf + off);
1514b690436dSAndreas Jaekel 				zev_eventstat(buf + off, ev->header.record_len);
1515b690436dSAndreas Jaekel 				off += ev->header.record_len;
1516b690436dSAndreas Jaekel 			}
1517b690436dSAndreas Jaekel 			off = 0;
1518b690436dSAndreas Jaekel 		} while ((t_now) < t_until && (ms > 0));
1519f432e238SAndreas Jaekel 		zev_eventstat_interval(out);
1520b690436dSAndreas Jaekel 		if (cnt > 0)
1521b690436dSAndreas Jaekel 			cnt--;
1522b690436dSAndreas Jaekel 	}
1523b690436dSAndreas Jaekel 	close(q_fd);
1524f432e238SAndreas Jaekel 	if (outfile)
1525f432e238SAndreas Jaekel 		fclose(out);
1526b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_interval))
1527b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_interval, gt);
1528b690436dSAndreas Jaekel 	while (gt = avl_first(&zevstat.guids_runtime)) {
1529b690436dSAndreas Jaekel 		avl_remove(&zevstat.guids_runtime, gt);
1530b690436dSAndreas Jaekel 		free(gt);
1531b690436dSAndreas Jaekel 	}
1532b690436dSAndreas Jaekel 	return EXIT_SUCCESS;
1533b690436dSAndreas Jaekel }
1534b690436dSAndreas Jaekel 
1535f432e238SAndreas Jaekel static int
zev_report(int fd,char * basename)1536f432e238SAndreas Jaekel zev_report(int fd, char *basename)
1537f432e238SAndreas Jaekel {
1538f432e238SAndreas Jaekel 	char filename[MAXPATHLEN];
1539f432e238SAndreas Jaekel 	char count[10];
1540f432e238SAndreas Jaekel 	time_t now;
1541f432e238SAndreas Jaekel 	time_t midnight;
1542f432e238SAndreas Jaekel 	struct tm tm;
1543f432e238SAndreas Jaekel 	int minutes;
1544f432e238SAndreas Jaekel 	int ret;
1545f432e238SAndreas Jaekel 
1546f432e238SAndreas Jaekel 	verbose++;
1547f432e238SAndreas Jaekel 	while (1) {
1548f432e238SAndreas Jaekel 		now = time(NULL);
1549f432e238SAndreas Jaekel 		localtime_r(&now, &tm);
1550f432e238SAndreas Jaekel 		snprintf(filename, sizeof(filename), "%s.%04d-%02d-%02d",
1551f432e238SAndreas Jaekel 		         basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
1552f432e238SAndreas Jaekel 		tm.tm_sec = 0;
1553f432e238SAndreas Jaekel 		tm.tm_min = 0;
1554f432e238SAndreas Jaekel 		tm.tm_hour = 0;
1555f432e238SAndreas Jaekel 		tm.tm_mday++;  /* works for Jan 32nd, Feb 30th, etc. */
1556f432e238SAndreas Jaekel 		midnight = mktime(&tm);
1557f432e238SAndreas Jaekel 		if (now % 60)
1558f432e238SAndreas Jaekel 			sleep(60 - (now % 60));
1559f432e238SAndreas Jaekel 		minutes = (midnight - time(NULL)) / 60;
1560f432e238SAndreas Jaekel 		snprintf(count, sizeof(count), "%d", minutes);
1561f432e238SAndreas Jaekel 		ret = zev_zevstat(fd, "60", count, filename);
1562f432e238SAndreas Jaekel 		if (ret)
1563f432e238SAndreas Jaekel 			return EXIT_FAILURE;
1564f432e238SAndreas Jaekel 	}
1565f432e238SAndreas Jaekel 	return EXIT_SUCCESS; /* never reached */
1566f432e238SAndreas Jaekel }
1567f432e238SAndreas Jaekel 
1568e3455c18SAndreas Jaekel static int
zev_get_zev_version(int fd)1569e3455c18SAndreas Jaekel zev_get_zev_version(int fd)
1570e3455c18SAndreas Jaekel {
1571e3455c18SAndreas Jaekel 	zev_ioctl_get_zev_version vi;
1572e3455c18SAndreas Jaekel 
1573e3455c18SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_ZEV_VERSION, &vi)) {
1574e3455c18SAndreas Jaekel 		perror("getting zev cersion info failed");
1575e3455c18SAndreas Jaekel 		return (EXIT_FAILURE);
1576e3455c18SAndreas Jaekel 	}
1577e3455c18SAndreas Jaekel 
1578e3455c18SAndreas Jaekel 	printf("zev major version: %llu\n", vi.zev_major_version);
1579e3455c18SAndreas Jaekel 	printf("zev minor version: %llu\n", vi.zev_minor_version);
1580e3455c18SAndreas Jaekel 	return 0;
1581e3455c18SAndreas Jaekel }
1582e3455c18SAndreas Jaekel 
1583a0d677d8SAndreas Jaekel static void
zev_sigint(int sig)1584a0d677d8SAndreas Jaekel zev_sigint(int sig)
1585a0d677d8SAndreas Jaekel {
1586a0d677d8SAndreas Jaekel 	fflush(stdout);
1587a0d677d8SAndreas Jaekel }
1588a0d677d8SAndreas Jaekel 
1589a18c35b9SAndreas Jaekel int
main(int argc,char ** argv)1590a18c35b9SAndreas Jaekel main(int argc, char **argv)
1591a18c35b9SAndreas Jaekel {
1592a18c35b9SAndreas Jaekel 	int fd;
1593a18c35b9SAndreas Jaekel 	int c;
1594a18c35b9SAndreas Jaekel 	extern char *optarg;
15956a6a51eeSAndreas Jaekel 	int create_tmp_queue = 1;
15966a6a51eeSAndreas Jaekel 	char buf[MAXPATHLEN];
1597a5090b97SAndreas Jaekel 	int mode = 0;
1598a5090b97SAndreas Jaekel 	char *arg = NULL;
1599a5090b97SAndreas Jaekel 	char *arg2 = NULL;
1600b690436dSAndreas Jaekel 	char *p;
1601b690436dSAndreas Jaekel 
1602a0d677d8SAndreas Jaekel 	sigset(SIGINT, zev_sigint);
1603a0d677d8SAndreas Jaekel 
160450da9edeSAndreas Jaekel 	/* open device */
160550da9edeSAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
160650da9edeSAndreas Jaekel 	if (fd < 0) {
160750da9edeSAndreas Jaekel 		perror("opening zev device failed");
160850da9edeSAndreas Jaekel 		return EXIT_FAILURE;
160950da9edeSAndreas Jaekel 	}
161050da9edeSAndreas Jaekel 
1611b690436dSAndreas Jaekel 	p = strrchr(argv[0], '/');
1612b690436dSAndreas Jaekel 	if (!p) {
1613b690436dSAndreas Jaekel 		p = argv[0];
1614b690436dSAndreas Jaekel 	} else {
1615b690436dSAndreas Jaekel 		p++;
1616b690436dSAndreas Jaekel 	}
1617b690436dSAndreas Jaekel 	if (!strcmp(p, "zevstat")) {
1618b690436dSAndreas Jaekel 		mode = MD_ZEVSTAT;
161950da9edeSAndreas Jaekel 		if (argc < 2)
162050da9edeSAndreas Jaekel 			zevstat_usage(argv[0]);
162150da9edeSAndreas Jaekel 		if (!strcmp(argv[1], "-v")) {
162250da9edeSAndreas Jaekel 			if (argc < 3)
162350da9edeSAndreas Jaekel 				zevstat_usage(argv[0]);
162450da9edeSAndreas Jaekel 			verbose++;
162550da9edeSAndreas Jaekel 			arg = argv[2];
162650da9edeSAndreas Jaekel 			arg2 = argv[3];
162750da9edeSAndreas Jaekel 		} else {
162850da9edeSAndreas Jaekel 			arg = argv[1];
162950da9edeSAndreas Jaekel 			arg2 = argv[2];
163050da9edeSAndreas Jaekel 		}
1631f432e238SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
1632f432e238SAndreas Jaekel 	} else if(!strcmp(p, "zevreport")) {
1633f432e238SAndreas Jaekel 		mode = MD_ZEV_REPORT;
1634f432e238SAndreas Jaekel 		if (argc != 2)
1635f432e238SAndreas Jaekel 			zevreport_usage(argv[0]);
1636f432e238SAndreas Jaekel 		return zev_report(fd, argv[1]);
1637b690436dSAndreas Jaekel 	}
1638a18c35b9SAndreas Jaekel 
16396a6a51eeSAndreas Jaekel 	while ((c = getopt(argc, argv,
1640*8cfb36b9SArne Jansen 	   "a:A:b:B:c:d:Df:FgG:hk:lL:m:M:pP:q:Q:r:R:st:T:vV?")) != -1) {
1641a18c35b9SAndreas Jaekel 		switch(c) {
164216ff6b2fSAndreas Jaekel 		case 'g':
164316ff6b2fSAndreas Jaekel 			grep_friendly++;
164416ff6b2fSAndreas Jaekel 			verbose++;
164516ff6b2fSAndreas Jaekel 			break;
1646205ed6bfSAndreas Jaekel 		case 'v':
1647205ed6bfSAndreas Jaekel 			verbose++;
1648205ed6bfSAndreas Jaekel 			break;
1649a18c35b9SAndreas Jaekel 		case 's':
1650a5090b97SAndreas Jaekel 			mode = MD_STATISTICS;
1651a5090b97SAndreas Jaekel 			break;
1652a18c35b9SAndreas Jaekel 		case 'p':
1653a5090b97SAndreas Jaekel 			mode = MD_POLL_EVENTS;
1654a5090b97SAndreas Jaekel 			break;
165542110aacSAndreas Jaekel 		case 'c':
1656a5090b97SAndreas Jaekel 			mode = MD_CHECKSUMS;
1657a5090b97SAndreas Jaekel 			arg = optarg;
1658a5090b97SAndreas Jaekel 			break;
1659add9520fSAndreas Jaekel 		case 'D':
1660a5090b97SAndreas Jaekel 			mode = MD_DEBUG_INFO;
1661a5090b97SAndreas Jaekel 			break;
1662a18c35b9SAndreas Jaekel 		case 'd':
1663add9520fSAndreas Jaekel 			close(fd);
1664a18c35b9SAndreas Jaekel 			zev_device = optarg;
1665add9520fSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1666add9520fSAndreas Jaekel 			if (fd < 0) {
1667add9520fSAndreas Jaekel 				perror("opening zev device failed");
1668add9520fSAndreas Jaekel 				return EXIT_FAILURE;
1669add9520fSAndreas Jaekel 			}
16706a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
16716a6a51eeSAndreas Jaekel 			break;
16726a6a51eeSAndreas Jaekel 		case 'q':
16736a6a51eeSAndreas Jaekel 			snprintf(buf, sizeof(buf),
16746a6a51eeSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
16756a6a51eeSAndreas Jaekel 			close(fd);
16766a6a51eeSAndreas Jaekel 			zev_device = buf;
16776a6a51eeSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
16786a6a51eeSAndreas Jaekel 			if (fd < 0) {
16796a6a51eeSAndreas Jaekel 				perror("opening zev device failed");
16806a6a51eeSAndreas Jaekel 				return EXIT_FAILURE;
16816a6a51eeSAndreas Jaekel 			}
16826a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
1683a18c35b9SAndreas Jaekel 			break;
168435526fb3SArne Jansen 		case 'f':
168535526fb3SArne Jansen 			fd = open(optarg, O_RDONLY);
168635526fb3SArne Jansen 			if (fd < 0) {
168735526fb3SArne Jansen 				perror("opening spool file failed");
168835526fb3SArne Jansen 				return EXIT_FAILURE;
168935526fb3SArne Jansen 			}
169035526fb3SArne Jansen 			mode = MD_DUMP_SPOOL;
169135526fb3SArne Jansen 			break;
1692add9520fSAndreas Jaekel 		case 'l':
1693a5090b97SAndreas Jaekel 			mode = MD_LIST_QUEUES;
1694a5090b97SAndreas Jaekel 			break;
1695add9520fSAndreas Jaekel 		case 'Q':
1696a5090b97SAndreas Jaekel 			mode = MD_SET_GLOBAL_MAX_QUEUE_LEN;
1697a5090b97SAndreas Jaekel 			arg = optarg;
1698a5090b97SAndreas Jaekel 			break;
16996a6a51eeSAndreas Jaekel 		case 'L':
1700a5090b97SAndreas Jaekel 			mode = MD_SET_MAX_QUEUE_LEN;
1701a5090b97SAndreas Jaekel 			arg = optarg;
1702a5090b97SAndreas Jaekel 			arg2 = argv[optind];
1703a5090b97SAndreas Jaekel 			break;
1704b690436dSAndreas Jaekel 		case 'T':
1705b690436dSAndreas Jaekel 			mode = MD_ZEVSTAT;
1706b690436dSAndreas Jaekel 			arg = optarg;
1707b690436dSAndreas Jaekel 			arg2 = argv[optind];
1708b690436dSAndreas Jaekel 			break;
1709f432e238SAndreas Jaekel 		case 'R':
1710f432e238SAndreas Jaekel 			mode = MD_ZEV_REPORT;
1711f432e238SAndreas Jaekel 			arg = optarg;
1712f432e238SAndreas Jaekel 			break;
1713fec460f8SAndreas Jaekel 		case 't':
1714a5090b97SAndreas Jaekel 			mode = MD_SET_POLL_WAKEUP_QUEUE_LEN;
1715a5090b97SAndreas Jaekel 			arg = optarg;
1716a5090b97SAndreas Jaekel 			arg2 = argv[optind];
1717a5090b97SAndreas Jaekel 			break;
1718a18c35b9SAndreas Jaekel 		case 'm':
1719a5090b97SAndreas Jaekel 			mode = MD_MUTE_POOL;
1720a5090b97SAndreas Jaekel 			arg = optarg;
1721a5090b97SAndreas Jaekel 			break;
1722a18c35b9SAndreas Jaekel 		case 'M':
1723a5090b97SAndreas Jaekel 			mode = MD_UNMUTE_POOL;
1724a5090b97SAndreas Jaekel 			arg = optarg;
1725a5090b97SAndreas Jaekel 			break;
1726888fea18SAndreas Jaekel 		case 'k':
1727a5090b97SAndreas Jaekel 			mode = MD_MARK;
1728a5090b97SAndreas Jaekel 			arg = optarg;
1729a5090b97SAndreas Jaekel 			break;
1730add9520fSAndreas Jaekel 		case 'a':
1731a5090b97SAndreas Jaekel 			mode = MD_ADD_QUEUE;
1732a5090b97SAndreas Jaekel 			arg = optarg;
1733a5090b97SAndreas Jaekel 			break;
17346a6a51eeSAndreas Jaekel 		case 'A':
1735a5090b97SAndreas Jaekel 			mode = MD_ADD_BLOCKING_QUEUE;
1736a5090b97SAndreas Jaekel 			arg = optarg;
1737a5090b97SAndreas Jaekel 			break;
1738add9520fSAndreas Jaekel 		case 'r':
1739a5090b97SAndreas Jaekel 			mode = MD_REMOVE_QUEUE;
1740a5090b97SAndreas Jaekel 			arg = optarg;
1741a5090b97SAndreas Jaekel 			break;
1742add9520fSAndreas Jaekel 		case 'b':
1743a5090b97SAndreas Jaekel 			mode = MD_QUEUE_BLOCKING;
1744a5090b97SAndreas Jaekel 			arg = optarg;
1745a5090b97SAndreas Jaekel 			break;
1746add9520fSAndreas Jaekel 		case 'B':
1747a5090b97SAndreas Jaekel 			mode = MD_QUEUE_NONBLOCKING;
1748a5090b97SAndreas Jaekel 			arg = optarg;
1749a5090b97SAndreas Jaekel 			break;
1750add9520fSAndreas Jaekel 		case 'P':
1751a5090b97SAndreas Jaekel 			mode = MD_QUEUE_PROPERTIES;
1752a5090b97SAndreas Jaekel 			arg = optarg;
1753a5090b97SAndreas Jaekel 			break;
1754*8cfb36b9SArne Jansen 		case 'G':
1755*8cfb36b9SArne Jansen 			if (num_guid_filter == MAX_GUID) {
1756*8cfb36b9SArne Jansen 				fprintf(stderr,
1757*8cfb36b9SArne Jansen 				 "too many guids given, max is %d\n", MAX_GUID);
1758*8cfb36b9SArne Jansen 				exit(1);
1759*8cfb36b9SArne Jansen 			}
1760*8cfb36b9SArne Jansen 			guid_filter[num_guid_filter++] = atoll(optarg);
1761*8cfb36b9SArne Jansen 			break;
1762e3455c18SAndreas Jaekel 		case 'V':
1763e3455c18SAndreas Jaekel 			mode = MD_GET_ZEV_VERSION;
1764e3455c18SAndreas Jaekel 			break;
1765342055d2SArne Jansen 		case 'F':
1766342055d2SArne Jansen 			do_flush = 1;
1767342055d2SArne Jansen 			break;
1768a18c35b9SAndreas Jaekel 		case 'h':
1769a18c35b9SAndreas Jaekel 		case '?':
1770a18c35b9SAndreas Jaekel 		default:
1771a18c35b9SAndreas Jaekel 			usage(argv[0]);
1772a18c35b9SAndreas Jaekel 		}
1773a18c35b9SAndreas Jaekel 	}
1774a5090b97SAndreas Jaekel 
1775a5090b97SAndreas Jaekel 	switch (mode) {
1776a5090b97SAndreas Jaekel 	case MD_STATISTICS:
1777a5090b97SAndreas Jaekel 		return zev_statistics(fd);
1778a5090b97SAndreas Jaekel 	case MD_POLL_EVENTS:
1779b64581b1SAndreas Jaekel 		return zev_poll_events(fd, create_tmp_queue);
178035526fb3SArne Jansen 	case MD_DUMP_SPOOL:
178135526fb3SArne Jansen 		return zev_dump_spool(fd);
1782a5090b97SAndreas Jaekel 	case MD_CHECKSUMS:
1783a5090b97SAndreas Jaekel 		return zev_checksum(fd, arg);
1784a5090b97SAndreas Jaekel 	case MD_DEBUG_INFO:
1785a5090b97SAndreas Jaekel 		return zev_debug_info(fd);
1786a5090b97SAndreas Jaekel 	case MD_LIST_QUEUES:
1787a5090b97SAndreas Jaekel 		return zev_list_queues(fd);
1788a5090b97SAndreas Jaekel 	case MD_SET_GLOBAL_MAX_QUEUE_LEN:
1789a5090b97SAndreas Jaekel 		return zev_set_global_max_queue_len(fd, arg);
1790a5090b97SAndreas Jaekel 	case MD_SET_MAX_QUEUE_LEN:
1791a5090b97SAndreas Jaekel 		return zev_set_max_queue_len(fd, arg, arg2);
1792a5090b97SAndreas Jaekel 	case MD_SET_POLL_WAKEUP_QUEUE_LEN:
1793a5090b97SAndreas Jaekel 		return zev_set_poll_wakeup_queue_len(fd, arg, arg2);
1794b690436dSAndreas Jaekel 	case MD_ZEVSTAT:
1795f432e238SAndreas Jaekel 		return zev_zevstat(fd, arg, arg2, NULL);
1796f432e238SAndreas Jaekel 	case MD_ZEV_REPORT:
1797f432e238SAndreas Jaekel 		return zev_report(fd, arg);
1798a5090b97SAndreas Jaekel 	case MD_MUTE_POOL:
1799a5090b97SAndreas Jaekel 		return zev_mute_pool(fd, arg);
1800a5090b97SAndreas Jaekel 	case MD_UNMUTE_POOL:
1801a5090b97SAndreas Jaekel 		return zev_unmute_pool(fd, arg);
1802a5090b97SAndreas Jaekel 	case MD_MARK:
1803a5090b97SAndreas Jaekel 		return zev_mark(fd, arg);
1804a5090b97SAndreas Jaekel 	case MD_ADD_QUEUE:
1805a5090b97SAndreas Jaekel 		return zev_add_queue(fd, arg, 0);
1806a5090b97SAndreas Jaekel 	case MD_ADD_BLOCKING_QUEUE:
1807a5090b97SAndreas Jaekel 		return zev_add_queue(fd, arg, 1);
1808a5090b97SAndreas Jaekel 	case MD_REMOVE_QUEUE:
1809a5090b97SAndreas Jaekel 		return zev_remove_queue(fd, arg);
1810a5090b97SAndreas Jaekel 	case MD_QUEUE_BLOCKING:
1811a5090b97SAndreas Jaekel 		return zev_queue_blocking(fd, arg, 0);
1812a5090b97SAndreas Jaekel 	case MD_QUEUE_NONBLOCKING:
1813a5090b97SAndreas Jaekel 		return zev_queue_blocking(fd, arg, 1);
1814a5090b97SAndreas Jaekel 	case MD_QUEUE_PROPERTIES:
1815a5090b97SAndreas Jaekel 		return zev_queue_properties(fd, arg);
1816e3455c18SAndreas Jaekel 	case MD_GET_ZEV_VERSION:
1817e3455c18SAndreas Jaekel 		return zev_get_zev_version(fd);
1818a5090b97SAndreas Jaekel 	default:
1819a18c35b9SAndreas Jaekel 		close(fd);
1820a5090b97SAndreas Jaekel 		usage(argv[0]);
1821add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1822a5090b97SAndreas Jaekel 	};
1823a18c35b9SAndreas Jaekel }
1824a18c35b9SAndreas Jaekel 
1825