xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision 2eabeab54425bbb6a05a68c325bd1273f133aaa3)
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>
12a18c35b9SAndreas Jaekel 
13add9520fSAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
14a18c35b9SAndreas Jaekel 
15a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
16a18c35b9SAndreas Jaekel 
17aafc540fSAndreas Jaekel static char *zev_op_name[] = {
1816ff6b2fSAndreas Jaekel 	"ERROR",
1916ff6b2fSAndreas Jaekel 	"MARK",
2016ff6b2fSAndreas Jaekel 	"ZFS_MOUNT",
2116ff6b2fSAndreas Jaekel 	"ZFS_UMOUNT",
2216ff6b2fSAndreas Jaekel 	"ZVOL_WRITE",
2316ff6b2fSAndreas Jaekel 	"ZVOL_TRUNCATE",
2416ff6b2fSAndreas Jaekel 	"ZNODE_CLOSE_AFTER_UPDATE",
2516ff6b2fSAndreas Jaekel 	"ZNODE_CREATE",
2616ff6b2fSAndreas Jaekel 	"ZNODE_MKDIR",
2716ff6b2fSAndreas Jaekel 	"ZNODE_MAKE_XATTR_DIR",
2816ff6b2fSAndreas Jaekel 	"ZNODE_REMOVE",
2916ff6b2fSAndreas Jaekel 	"ZNODE_RMDIR",
3016ff6b2fSAndreas Jaekel 	"ZNODE_LINK",
3116ff6b2fSAndreas Jaekel 	"ZNODE_SYMLINK",
3216ff6b2fSAndreas Jaekel 	"ZNODE_RENAME",
3316ff6b2fSAndreas Jaekel 	"ZNODE_WRITE",
3416ff6b2fSAndreas Jaekel 	"ZNODE_TRUNCATE",
3516ff6b2fSAndreas Jaekel 	"ZNODE_SETATTR",
3616ff6b2fSAndreas Jaekel 	"ZNODE_ACL",
37aafc540fSAndreas Jaekel 	NULL
38aafc540fSAndreas Jaekel };
39aafc540fSAndreas Jaekel 
40205ed6bfSAndreas Jaekel static int verbose = 0;
4116ff6b2fSAndreas Jaekel static int grep_friendly = 0;
4216ff6b2fSAndreas Jaekel 
4316ff6b2fSAndreas Jaekel static void
4416ff6b2fSAndreas Jaekel zpf(char *fmt, ...)
4516ff6b2fSAndreas Jaekel {
4616ff6b2fSAndreas Jaekel 	va_list	ap;
4716ff6b2fSAndreas Jaekel 
4816ff6b2fSAndreas Jaekel 	va_start(ap, fmt);
4916ff6b2fSAndreas Jaekel 	vprintf(fmt, ap);
5016ff6b2fSAndreas Jaekel 	va_end(ap);
5116ff6b2fSAndreas Jaekel 	if (grep_friendly) {
5216ff6b2fSAndreas Jaekel 		printf(" ");
5316ff6b2fSAndreas Jaekel 	} else {
5416ff6b2fSAndreas Jaekel 		printf("\n");
5516ff6b2fSAndreas Jaekel 	}
5616ff6b2fSAndreas Jaekel }
5716ff6b2fSAndreas Jaekel 
5816ff6b2fSAndreas Jaekel static void
5916ff6b2fSAndreas Jaekel znl(void)
6016ff6b2fSAndreas Jaekel {
6116ff6b2fSAndreas Jaekel 	if (grep_friendly)
6216ff6b2fSAndreas Jaekel 		printf("\n");
6316ff6b2fSAndreas Jaekel }
64205ed6bfSAndreas Jaekel 
65*2eabeab5SAndreas Jaekel static void
66*2eabeab5SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
67*2eabeab5SAndreas Jaekel {
68*2eabeab5SAndreas Jaekel 	int     i;
69*2eabeab5SAndreas Jaekel 
70*2eabeab5SAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
71*2eabeab5SAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
72*2eabeab5SAndreas Jaekel 	}
73*2eabeab5SAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
74*2eabeab5SAndreas Jaekel }
75*2eabeab5SAndreas Jaekel 
76add9520fSAndreas Jaekel static int
77a18c35b9SAndreas Jaekel zev_statistics(int fd)
78a18c35b9SAndreas Jaekel {
79a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
80add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
81a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
82add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
83a18c35b9SAndreas Jaekel 	}
84a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
85a18c35b9SAndreas Jaekel 
86a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
87a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
88a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
89a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
90a18c35b9SAndreas Jaekel 
91add9520fSAndreas Jaekel 	printf("    discarded events        : %lu\n",
92add9520fSAndreas Jaekel 	    zs.zev_cnt_discarded_events);
93add9520fSAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
94add9520fSAndreas Jaekel 
95a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
96a18c35b9SAndreas Jaekel 
97a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
98a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
99a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
100a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
101a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
102a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
103a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
104a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
105a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
106a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
107a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
108a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
109a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
110a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
111a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
112a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
113a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
114add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
115a18c35b9SAndreas Jaekel }
116a18c35b9SAndreas Jaekel 
117a18c35b9SAndreas Jaekel static void
11816ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info)
11916ff6b2fSAndreas Jaekel {
12016ff6b2fSAndreas Jaekel 	zpf("  %s.inode: %llu", name, info->ino);
12116ff6b2fSAndreas Jaekel 	zpf("  %s.gen: %llu", name, info->gen);
12216ff6b2fSAndreas Jaekel 	zpf("  %s.mtime: %llu", name, info->mtime);
12316ff6b2fSAndreas Jaekel 	zpf("  %s.ctime: %llu", name, info->ctime);
12416ff6b2fSAndreas Jaekel 	zpf("  %s.size: %llu", name, info->size);
12516ff6b2fSAndreas Jaekel 	zpf("  %s.mode: %llo", name, info->mode);
12616ff6b2fSAndreas Jaekel 	zpf("  %s.links: %llu", name, info->links);
12716ff6b2fSAndreas Jaekel 	zpf("  %s.type: %lu", name, info->type);
12816ff6b2fSAndreas Jaekel 	zpf("  %s.flags: %lu", name, info->flags);
12916ff6b2fSAndreas Jaekel }
13016ff6b2fSAndreas Jaekel 
13116ff6b2fSAndreas Jaekel static void
13216ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec)
13316ff6b2fSAndreas Jaekel {
13416ff6b2fSAndreas Jaekel 	int i;
13516ff6b2fSAndreas Jaekel 	int j;
13616ff6b2fSAndreas Jaekel 	uint8_t *p;
13716ff6b2fSAndreas Jaekel 	char c;
13816ff6b2fSAndreas Jaekel 
13916ff6b2fSAndreas Jaekel 	zpf("  payload:");
14016ff6b2fSAndreas Jaekel 	p = (uint8_t *)ZEV_PAYLOAD(rec);
14116ff6b2fSAndreas Jaekel 	for (i=0; i<rec->payload_len; i+=16) {
14216ff6b2fSAndreas Jaekel 		printf("  ");
14316ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
14416ff6b2fSAndreas Jaekel 			printf("%02x ", p[j]);
14516ff6b2fSAndreas Jaekel 			if (j == i + 7)
14616ff6b2fSAndreas Jaekel 				printf(" ");
14716ff6b2fSAndreas Jaekel 		}
14816ff6b2fSAndreas Jaekel 		if (grep_friendly)
14916ff6b2fSAndreas Jaekel 			continue;
15016ff6b2fSAndreas Jaekel 		for (; j<i+16; j++) {
15116ff6b2fSAndreas Jaekel 			printf("   ");
15216ff6b2fSAndreas Jaekel 			if (j == i + 7)
15316ff6b2fSAndreas Jaekel 				printf(" ");
15416ff6b2fSAndreas Jaekel 		}
15516ff6b2fSAndreas Jaekel 		printf("    ");
15616ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
15716ff6b2fSAndreas Jaekel 			c = '.';
15816ff6b2fSAndreas Jaekel 			if (p[j] >= ' ' && p[j] <= '~')
15916ff6b2fSAndreas Jaekel 				c = p[j];
16016ff6b2fSAndreas Jaekel 			printf("%c", c);
16116ff6b2fSAndreas Jaekel 			if (j == i + 7)
16216ff6b2fSAndreas Jaekel 				printf(" ");
16316ff6b2fSAndreas Jaekel 		}
16416ff6b2fSAndreas Jaekel 		printf("\n");
16516ff6b2fSAndreas Jaekel 	}
16616ff6b2fSAndreas Jaekel }
16716ff6b2fSAndreas Jaekel 
16816ff6b2fSAndreas Jaekel static void
169f2dd45e5SAndreas Jaekel zev_print_error(char *buf)
170f2dd45e5SAndreas Jaekel {
171f2dd45e5SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
172f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
173f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
174f2dd45e5SAndreas Jaekel 
17516ff6b2fSAndreas Jaekel 	if (verbose) {
17616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
17716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
17816ff6b2fSAndreas Jaekel 		zpf("  failed.op: %s",
17916ff6b2fSAndreas Jaekel 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
18016ff6b2fSAndreas Jaekel 		zpf("  message: %s", ZEV_ERRSTR(rec));
18116ff6b2fSAndreas Jaekel 		znl();
18216ff6b2fSAndreas Jaekel 	} else {
183f2dd45e5SAndreas Jaekel 		printf("%s %s: failed_op=%s msg=%s\n",
184f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
18516ff6b2fSAndreas Jaekel 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
18616ff6b2fSAndreas Jaekel 		       ZEV_ERRSTR(rec));
18716ff6b2fSAndreas Jaekel 	}
188f2dd45e5SAndreas Jaekel }
189f2dd45e5SAndreas Jaekel 
190f2dd45e5SAndreas Jaekel static void
191888fea18SAndreas Jaekel zev_print_mark(char *buf)
192888fea18SAndreas Jaekel {
193888fea18SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
194888fea18SAndreas Jaekel 	time_t op_time = rec->op_time;
195888fea18SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
196888fea18SAndreas Jaekel 
19716ff6b2fSAndreas Jaekel 	if (verbose) {
19816ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
19916ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
20016ff6b2fSAndreas Jaekel 		zpf("  mark.id: %llu", rec->mark_id);
20116ff6b2fSAndreas Jaekel 		zpf("  payload.len: %llu", rec->payload_len);
20216ff6b2fSAndreas Jaekel 		if (rec->payload_len)
20316ff6b2fSAndreas Jaekel 			zev_print_mark_payload(rec);
20416ff6b2fSAndreas Jaekel 		znl();
20516ff6b2fSAndreas Jaekel 	} else {
206888fea18SAndreas Jaekel 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
20716ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
20816ff6b2fSAndreas Jaekel 		       rec->mark_id, rec->payload_len);
20916ff6b2fSAndreas Jaekel 	}
210888fea18SAndreas Jaekel }
211888fea18SAndreas Jaekel 
212888fea18SAndreas Jaekel static void
213f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf)
214f2dd45e5SAndreas Jaekel {
215f2dd45e5SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
216f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
217f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
218f2dd45e5SAndreas Jaekel 
21916ff6b2fSAndreas Jaekel 	if (verbose) {
22016ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
22116ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
22216ff6b2fSAndreas Jaekel 		zpf("  dataset: %s", ZEV_DATASET(rec));
22316ff6b2fSAndreas Jaekel 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
22416ff6b2fSAndreas Jaekel 		zpf("  remount: %s", rec->remount ? "true" : "false");
22516ff6b2fSAndreas Jaekel 		zev_print_inode_info("root", &rec->root);
22616ff6b2fSAndreas Jaekel 		znl();
22716ff6b2fSAndreas Jaekel 	} else {
22816ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
22916ff6b2fSAndreas Jaekel 		       "mountpoint='%s'\n",
230f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
231f2dd45e5SAndreas Jaekel 		       rec->guid,
232f2dd45e5SAndreas Jaekel 		       rec->remount ? "true" : "false",
233f2dd45e5SAndreas Jaekel 		       ZEV_DATASET(rec),
234f2dd45e5SAndreas Jaekel 		       ZEV_MOUNTPOINT(rec));
235f2dd45e5SAndreas Jaekel 	}
23616ff6b2fSAndreas Jaekel }
237f2dd45e5SAndreas Jaekel 
238f2dd45e5SAndreas Jaekel static void
239f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf)
240f2dd45e5SAndreas Jaekel {
241f2dd45e5SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
242f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
243f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
244f2dd45e5SAndreas Jaekel 
24516ff6b2fSAndreas Jaekel 	if (verbose) {
24616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
24716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
24816ff6b2fSAndreas Jaekel 		znl();
24916ff6b2fSAndreas Jaekel 	} else {
250f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
251f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
252f2dd45e5SAndreas Jaekel 		       rec->guid);
253f2dd45e5SAndreas Jaekel 	}
25416ff6b2fSAndreas Jaekel }
255f2dd45e5SAndreas Jaekel 
256f2dd45e5SAndreas Jaekel static void
257f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf)
258f2dd45e5SAndreas Jaekel {
259f2dd45e5SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
260f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
261f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
262f2dd45e5SAndreas Jaekel 
26316ff6b2fSAndreas Jaekel 	if (verbose) {
26416ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
26516ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
26612119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
26716ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
26816ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
26916ff6b2fSAndreas Jaekel 		znl();
27016ff6b2fSAndreas Jaekel 	} else {
271f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
272f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
273f2dd45e5SAndreas Jaekel 		       rec->guid,
274f2dd45e5SAndreas Jaekel 		       rec->offset,
275f2dd45e5SAndreas Jaekel 		       rec->length);
276f2dd45e5SAndreas Jaekel 	}
27716ff6b2fSAndreas Jaekel }
278f2dd45e5SAndreas Jaekel 
279f2dd45e5SAndreas Jaekel static void
280f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf)
281f2dd45e5SAndreas Jaekel {
282f2dd45e5SAndreas Jaekel 	zev_print_zvol_truncate(buf);
283f2dd45e5SAndreas Jaekel }
284f2dd45e5SAndreas Jaekel 
285f2dd45e5SAndreas Jaekel static void
286f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
287f2dd45e5SAndreas Jaekel {
288f2dd45e5SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
289f2dd45e5SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
290f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
291f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
292f2dd45e5SAndreas Jaekel 
29316ff6b2fSAndreas Jaekel 	if (verbose) {
29416ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
29516ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
29616ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
29716ff6b2fSAndreas Jaekel 		znl();
29816ff6b2fSAndreas Jaekel 	} else {
299f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
300f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
301f2dd45e5SAndreas Jaekel 		       rec->guid,
302f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
303f2dd45e5SAndreas Jaekel 	}
30416ff6b2fSAndreas Jaekel }
305f2dd45e5SAndreas Jaekel 
306f2dd45e5SAndreas Jaekel static void
307f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf)
308f2dd45e5SAndreas Jaekel {
309f2dd45e5SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
310f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
311f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
312*2eabeab5SAndreas Jaekel 	zev_sig_t *sig;
313*2eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
314f2dd45e5SAndreas Jaekel 
31516ff6b2fSAndreas Jaekel 	if (verbose) {
31616ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
31716ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
31812119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
31916ff6b2fSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
320*2eabeab5SAndreas Jaekel 		sig = &rec->signature;
321*2eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
322*2eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
323*2eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
32416ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
32512119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
32616ff6b2fSAndreas Jaekel 		znl();
32716ff6b2fSAndreas Jaekel 	} else {
32835d4e8ddSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
32935d4e8ddSAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
330f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
331f2dd45e5SAndreas Jaekel 		       rec->guid,
332f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
333f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
33435d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
335f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
336f2dd45e5SAndreas Jaekel 	}
33716ff6b2fSAndreas Jaekel }
338f2dd45e5SAndreas Jaekel 
339f2dd45e5SAndreas Jaekel static void
340f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf)
341f2dd45e5SAndreas Jaekel {
342f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
343f2dd45e5SAndreas Jaekel }
344f2dd45e5SAndreas Jaekel 
345f2dd45e5SAndreas Jaekel static void
346f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
347f2dd45e5SAndreas Jaekel {
348f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
349f2dd45e5SAndreas Jaekel }
350f2dd45e5SAndreas Jaekel 
351f2dd45e5SAndreas Jaekel static void
352f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf)
353f2dd45e5SAndreas Jaekel {
354f2dd45e5SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
355f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
356f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
357f2dd45e5SAndreas Jaekel 
35816ff6b2fSAndreas Jaekel 	if (verbose) {
35916ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
36016ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
36112119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
36216ff6b2fSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
36316ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
36412119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
36516ff6b2fSAndreas Jaekel 		znl();
36616ff6b2fSAndreas Jaekel 	} else {
36716ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
36816ff6b2fSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
369f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
370f2dd45e5SAndreas Jaekel 		       rec->guid,
371f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
37297dcf88dSAndreas Jaekel 		       rec->file.mtime,
373f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
374f2dd45e5SAndreas Jaekel 	}
37516ff6b2fSAndreas Jaekel }
376f2dd45e5SAndreas Jaekel 
377f2dd45e5SAndreas Jaekel static void
378f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf)
379f2dd45e5SAndreas Jaekel {
380f2dd45e5SAndreas Jaekel 	zev_print_znode_remove(buf);
381f2dd45e5SAndreas Jaekel }
382f2dd45e5SAndreas Jaekel 
383f2dd45e5SAndreas Jaekel static void
384f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf)
385f2dd45e5SAndreas Jaekel {
386f2dd45e5SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
387f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
388f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
389f2dd45e5SAndreas Jaekel 
39016ff6b2fSAndreas Jaekel 	if (verbose) {
39116ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
39216ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
39312119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
39416ff6b2fSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
39516ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
39612119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
39716ff6b2fSAndreas Jaekel 		znl();
39816ff6b2fSAndreas Jaekel 	} else {
399a01b300aSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
400a01b300aSAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
401f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
402f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
403f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
404a01b300aSAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
405f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
40616ff6b2fSAndreas Jaekel 	}
407f2dd45e5SAndreas Jaekel }
408f2dd45e5SAndreas Jaekel 
409f2dd45e5SAndreas Jaekel static void
410f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf)
411f2dd45e5SAndreas Jaekel {
412f2dd45e5SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
413f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
414f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
415*2eabeab5SAndreas Jaekel 	zev_sig_t *sig;
416*2eabeab5SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
417f2dd45e5SAndreas Jaekel 
41816ff6b2fSAndreas Jaekel 	if (verbose) {
41916ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
42016ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
42112119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
42216ff6b2fSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
42316ff6b2fSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
424*2eabeab5SAndreas Jaekel 		sig = &rec->signature;
425*2eabeab5SAndreas Jaekel 		sig2hex_direct(sig->value, sigval);
426*2eabeab5SAndreas Jaekel 		zpf("  sig: level %d, offset %llu, value %s",
427*2eabeab5SAndreas Jaekel 		    sig->level, sig->block_offset, sigval);
42816ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
42912119a7eSAndreas Jaekel 		zev_print_inode_info("parent", &rec->parent);
43016ff6b2fSAndreas Jaekel 		znl();
43116ff6b2fSAndreas Jaekel 	} else {
43216ff6b2fSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
43316ff6b2fSAndreas Jaekel 		       "name='%s' link='%s'\n",
434f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
435f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
436f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
437f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec),
438f2dd45e5SAndreas Jaekel 		       ZEV_LINK(rec));
439f2dd45e5SAndreas Jaekel 	}
44016ff6b2fSAndreas Jaekel }
441f2dd45e5SAndreas Jaekel 
442f2dd45e5SAndreas Jaekel static void
443f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf)
444f2dd45e5SAndreas Jaekel {
445f2dd45e5SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
446f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
447f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
448f2dd45e5SAndreas Jaekel 
44916ff6b2fSAndreas Jaekel 	if (verbose) {
45016ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
45116ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
45212119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
45316ff6b2fSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
45416ff6b2fSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
45516ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
45616ff6b2fSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
45716ff6b2fSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
45816ff6b2fSAndreas Jaekel 		znl();
45916ff6b2fSAndreas Jaekel 	} else {
46016ff6b2fSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
46116ff6b2fSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
46216ff6b2fSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
46316ff6b2fSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
464f2dd45e5SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
465f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
466f2dd45e5SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
467f2dd45e5SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
468f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
46935d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
47035d4e8ddSAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
47135d4e8ddSAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
472f2dd45e5SAndreas Jaekel 		       ZEV_SRCNAME(rec),
473f2dd45e5SAndreas Jaekel 		       ZEV_DSTNAME(rec));
474f2dd45e5SAndreas Jaekel 	}
47516ff6b2fSAndreas Jaekel }
476f2dd45e5SAndreas Jaekel 
477f2dd45e5SAndreas Jaekel static void
478f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf)
479f2dd45e5SAndreas Jaekel {
480f2dd45e5SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
481f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
482f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
483205ed6bfSAndreas Jaekel 	zev_sig_t *sig;
484205ed6bfSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
485205ed6bfSAndreas Jaekel 	int i;
486f2dd45e5SAndreas Jaekel 
487205ed6bfSAndreas 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("  offset: %llu", rec->offset);
49216ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
49316ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
49416ff6b2fSAndreas Jaekel 		znl();
495205ed6bfSAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
496205ed6bfSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
497205ed6bfSAndreas Jaekel 			sig += i;
498205ed6bfSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
499*2eabeab5SAndreas Jaekel 			zpf("  sig: level %d, offset %llu, value %s",
500205ed6bfSAndreas Jaekel 			    sig->level, sig->block_offset, sigval);
501205ed6bfSAndreas Jaekel 		}
50216ff6b2fSAndreas Jaekel 	} else {
50316ff6b2fSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
50416ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
50516ff6b2fSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
50616ff6b2fSAndreas Jaekel 		       rec->offset, rec->length);
507205ed6bfSAndreas Jaekel 	}
508f2dd45e5SAndreas Jaekel }
509f2dd45e5SAndreas Jaekel 
510f2dd45e5SAndreas Jaekel static void
511f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf)
512f2dd45e5SAndreas Jaekel {
513f2dd45e5SAndreas Jaekel 	zev_print_znode_write(buf);
514f2dd45e5SAndreas Jaekel }
515f2dd45e5SAndreas Jaekel 
516f2dd45e5SAndreas Jaekel static void
517f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf)
518f2dd45e5SAndreas Jaekel {
519f2dd45e5SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
520f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
521f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
522f2dd45e5SAndreas Jaekel 
52316ff6b2fSAndreas Jaekel 	if (verbose) {
52416ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
52516ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
52612119a7eSAndreas Jaekel 		zpf("  txg: %llu", rec->txg);
52716ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
52816ff6b2fSAndreas Jaekel 		znl();
52916ff6b2fSAndreas Jaekel 	} else {
53035d4e8ddSAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
531f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
53235d4e8ddSAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
533f2dd45e5SAndreas Jaekel 	}
53416ff6b2fSAndreas Jaekel }
535f2dd45e5SAndreas Jaekel 
536f2dd45e5SAndreas Jaekel static void
537f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf)
538f2dd45e5SAndreas Jaekel {
539f2dd45e5SAndreas Jaekel 	zev_print_znode_setattr(buf);
540f2dd45e5SAndreas Jaekel }
541f2dd45e5SAndreas Jaekel 
542f2dd45e5SAndreas Jaekel static void
543aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
544aafc540fSAndreas Jaekel {
545f2dd45e5SAndreas Jaekel 	int record_len;
546f2dd45e5SAndreas Jaekel 	int op;
547aafc540fSAndreas Jaekel 
548f2dd45e5SAndreas Jaekel 	record_len = *(uint32_t *)buf;
549f2dd45e5SAndreas Jaekel 	if (record_len != len) {
550f2dd45e5SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
551f2dd45e5SAndreas Jaekel 		        record_len, len);
552aafc540fSAndreas Jaekel 		exit(1);
553aafc540fSAndreas Jaekel 	}
554f2dd45e5SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
555aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
556f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
557aafc540fSAndreas Jaekel 		exit(1);
558aafc540fSAndreas Jaekel 	}
559f2dd45e5SAndreas Jaekel 	switch (op) {
560f2dd45e5SAndreas Jaekel 	case ZEV_OP_ERROR:
561f2dd45e5SAndreas Jaekel 		zev_print_error(buf);
562aafc540fSAndreas Jaekel 		break;
563888fea18SAndreas Jaekel 	case ZEV_OP_MARK:
564888fea18SAndreas Jaekel 		zev_print_mark(buf);
565888fea18SAndreas Jaekel 		break;
566f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
567f2dd45e5SAndreas Jaekel 		zev_print_zfs_mount(buf);
568aafc540fSAndreas Jaekel 		break;
569f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
570f2dd45e5SAndreas Jaekel 		zev_print_zfs_umount(buf);
571aafc540fSAndreas Jaekel 		break;
572f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
573f2dd45e5SAndreas Jaekel 		zev_print_zvol_truncate(buf);
574aafc540fSAndreas Jaekel 		break;
575f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
576f2dd45e5SAndreas Jaekel 		zev_print_zvol_write(buf);
577f2dd45e5SAndreas Jaekel 		break;
578f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
579f2dd45e5SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
580f2dd45e5SAndreas Jaekel 		break;
581f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
582f2dd45e5SAndreas Jaekel 		zev_print_znode_create(buf);
583f2dd45e5SAndreas Jaekel 		break;
584f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
585f2dd45e5SAndreas Jaekel 		zev_print_znode_mkdir(buf);
586f2dd45e5SAndreas Jaekel 		break;
587f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
588f2dd45e5SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
589f2dd45e5SAndreas Jaekel 		break;
590f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
591f2dd45e5SAndreas Jaekel 		zev_print_znode_remove(buf);
592f2dd45e5SAndreas Jaekel 		break;
593f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
594f2dd45e5SAndreas Jaekel 		zev_print_znode_rmdir(buf);
595f2dd45e5SAndreas Jaekel 		break;
596f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
597f2dd45e5SAndreas Jaekel 		zev_print_znode_link(buf);
598f2dd45e5SAndreas Jaekel 		break;
599f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
600f2dd45e5SAndreas Jaekel 		zev_print_znode_symlink(buf);
601f2dd45e5SAndreas Jaekel 		break;
602f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
603f2dd45e5SAndreas Jaekel 		zev_print_znode_rename(buf);
604f2dd45e5SAndreas Jaekel 		break;
605f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
606f2dd45e5SAndreas Jaekel 		zev_print_znode_write(buf);
607f2dd45e5SAndreas Jaekel 		break;
608f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
609f2dd45e5SAndreas Jaekel 		zev_print_znode_truncate(buf);
610f2dd45e5SAndreas Jaekel 		break;
611f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
612f2dd45e5SAndreas Jaekel 		zev_print_znode_setattr(buf);
613f2dd45e5SAndreas Jaekel 		break;
614f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
615f2dd45e5SAndreas Jaekel 		zev_print_znode_acl(buf);
616aafc540fSAndreas Jaekel 		break;
617aafc540fSAndreas Jaekel 	default:
618f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
619aafc540fSAndreas Jaekel 		exit(1);
620aafc540fSAndreas Jaekel 	}
621aafc540fSAndreas Jaekel }
622aafc540fSAndreas Jaekel 
623add9520fSAndreas Jaekel static int
6246a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
625a18c35b9SAndreas Jaekel {
626a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
627a18c35b9SAndreas Jaekel 	int ret;
628aafc540fSAndreas Jaekel 	char buf[4096];
629d979f56cSAndreas Jaekel 	zev_event_t *ev;
630d979f56cSAndreas Jaekel 	int off = 0;
631add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
632add9520fSAndreas Jaekel 	int q_fd;
633add9520fSAndreas Jaekel 
6346a6a51eeSAndreas Jaekel 	if (create_tmp_queue) {
635add9520fSAndreas Jaekel 		aq.zev_max_queue_len = 0;
636add9520fSAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
637add9520fSAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
638add9520fSAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
639add9520fSAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
640add9520fSAndreas Jaekel 
641add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
642add9520fSAndreas Jaekel 			perror("adding temporary queue failed");
643add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
644add9520fSAndreas Jaekel 		}
645add9520fSAndreas Jaekel 
6466a6a51eeSAndreas Jaekel 		snprintf(buf, sizeof(buf),
6476a6a51eeSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
648add9520fSAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
649add9520fSAndreas Jaekel 		if (q_fd < 0) {
650add9520fSAndreas Jaekel 			perror("opening queue device failed");
651add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
652add9520fSAndreas Jaekel 		}
6536a6a51eeSAndreas Jaekel 	} else {
6546a6a51eeSAndreas Jaekel 		q_fd = fd;
6556a6a51eeSAndreas Jaekel 	}
656add9520fSAndreas Jaekel 
657a18c35b9SAndreas Jaekel 	while (1) {
658add9520fSAndreas Jaekel 		pfd[0].fd = q_fd;
659a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
660a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
661a18c35b9SAndreas Jaekel 		if (ret < 0) {
662a18c35b9SAndreas Jaekel 			perror("poll failed");
6636a6a51eeSAndreas Jaekel 			close(q_fd);
664add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
665a18c35b9SAndreas Jaekel 		}
666a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
667a18c35b9SAndreas Jaekel 			continue;
668a18c35b9SAndreas Jaekel 		/* data available */
669add9520fSAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
670a18c35b9SAndreas Jaekel 		if (ret < 0) {
671a18c35b9SAndreas Jaekel 			perror("read failed");
6726a6a51eeSAndreas Jaekel 			close(q_fd);
673add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
674a18c35b9SAndreas Jaekel 		}
675a18c35b9SAndreas Jaekel 		if (ret == 0)
676a18c35b9SAndreas Jaekel 			continue;
677d979f56cSAndreas Jaekel 		while (ret > off) {
678d979f56cSAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
679d979f56cSAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
680d979f56cSAndreas Jaekel 			off += ev->header.record_len;
681d979f56cSAndreas Jaekel 		}
682149d0affSAndreas Jaekel 		off = 0;
683a18c35b9SAndreas Jaekel 	}
6846a6a51eeSAndreas Jaekel 	if (create_tmp_queue)
685add9520fSAndreas Jaekel 		close(q_fd);
686add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
687a18c35b9SAndreas Jaekel }
688a18c35b9SAndreas Jaekel 
689a18c35b9SAndreas Jaekel static void
690a18c35b9SAndreas Jaekel usage(char *progname)
691a18c35b9SAndreas Jaekel {
692add9520fSAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
693add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
694add9520fSAndreas Jaekel 	fprintf(stderr, " Status information:\n");
695a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
696a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
697add9520fSAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
698add9520fSAndreas Jaekel 	        "information\n");
699add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
700add9520fSAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
701add9520fSAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
702add9520fSAndreas Jaekel 	        "length\n");
703add9520fSAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
704add9520fSAndreas Jaekel 	        "this pool\n");
705a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
706add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
707add9520fSAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
708add9520fSAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
7096a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
7106a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
711add9520fSAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
712add9520fSAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
713add9520fSAndreas Jaekel 	        "(default)\n");
714add9520fSAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
715add9520fSAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
7166a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
717add9520fSAndreas Jaekel 	        "length\n");
718add9520fSAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
719add9520fSAndreas Jaekel 	        "throttle\n");
720add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
721add9520fSAndreas Jaekel 	fprintf(stderr, " Other options:\n");
722add9520fSAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
723add9520fSAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
7246a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
7256a6a51eeSAndreas Jaekel 		"queue name\n");
726888fea18SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
72742110aacSAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
72842110aacSAndreas Jaekel 		"checksums\n");
72916ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
730205ed6bfSAndreas Jaekel 	        "for some operations\n");
73116ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
73216ff6b2fSAndreas Jaekel 	        "one event per line\n");
733a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
734a18c35b9SAndreas Jaekel }
735a18c35b9SAndreas Jaekel 
736a18c35b9SAndreas Jaekel static int
7376a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
738a18c35b9SAndreas Jaekel {
739add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
740add9520fSAndreas Jaekel 	int namelen;
741a18c35b9SAndreas Jaekel 
742add9520fSAndreas Jaekel 	namelen = strlen(arg);
743add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
744add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
745a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
746a18c35b9SAndreas Jaekel 	}
747add9520fSAndreas Jaekel 
748add9520fSAndreas Jaekel 	aq.zev_namelen = namelen;
749add9520fSAndreas Jaekel 	strcpy(aq.zev_name, arg);
7506a6a51eeSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;
7516a6a51eeSAndreas Jaekel 	if (blocking) {
7526a6a51eeSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
7536a6a51eeSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
7546a6a51eeSAndreas Jaekel 	} else {
755add9520fSAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
7566a6a51eeSAndreas Jaekel 	}
757add9520fSAndreas Jaekel 
758add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
759add9520fSAndreas Jaekel 		perror("adding queue failed");
760a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
761a18c35b9SAndreas Jaekel 	}
762a18c35b9SAndreas Jaekel 	return (0);
763a18c35b9SAndreas Jaekel }
764a18c35b9SAndreas Jaekel 
765a18c35b9SAndreas Jaekel static int
766add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg)
767fec460f8SAndreas Jaekel {
768add9520fSAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
769add9520fSAndreas Jaekel 	int namelen;
770fec460f8SAndreas Jaekel 
771add9520fSAndreas Jaekel 	namelen = strlen(arg);
772add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
773add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
774fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
775fec460f8SAndreas Jaekel 	}
776add9520fSAndreas Jaekel 
7776a6a51eeSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
7786a6a51eeSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
779add9520fSAndreas Jaekel 
780add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
781add9520fSAndreas Jaekel 		perror("removing queue failed");
782add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
783add9520fSAndreas Jaekel 	}
784add9520fSAndreas Jaekel 	return (0);
785add9520fSAndreas Jaekel }
786add9520fSAndreas Jaekel 
787add9520fSAndreas Jaekel static int
788add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
789add9520fSAndreas Jaekel {
790add9520fSAndreas Jaekel 	uint64_t maxqueuelen;
791add9520fSAndreas Jaekel 
792add9520fSAndreas Jaekel 	errno = 0;
793add9520fSAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
794add9520fSAndreas Jaekel 	if (errno) {
795add9520fSAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
796add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
797add9520fSAndreas Jaekel 	}
798add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
799add9520fSAndreas Jaekel 		perror("setting max queue length failed");
800fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
801fec460f8SAndreas Jaekel 	}
802fec460f8SAndreas Jaekel 	return (0);
803fec460f8SAndreas Jaekel }
804fec460f8SAndreas Jaekel 
805fec460f8SAndreas Jaekel static int
806a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
807a18c35b9SAndreas Jaekel {
808a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
809a18c35b9SAndreas Jaekel 	int len;
810a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
811a18c35b9SAndreas Jaekel 	len = strlen(poolname);
812a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
813a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
814a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
815a18c35b9SAndreas Jaekel 	}
816a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
817a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
818a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
819a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
820a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
821a18c35b9SAndreas Jaekel 	}
822a18c35b9SAndreas Jaekel 	return (0);
823a18c35b9SAndreas Jaekel }
824a18c35b9SAndreas Jaekel 
825a18c35b9SAndreas Jaekel int
826a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
827a18c35b9SAndreas Jaekel {
828a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
829a18c35b9SAndreas Jaekel }
830a18c35b9SAndreas Jaekel 
831a18c35b9SAndreas Jaekel int
832a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
833a18c35b9SAndreas Jaekel {
834a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
835a18c35b9SAndreas Jaekel }
836a18c35b9SAndreas Jaekel 
837888fea18SAndreas Jaekel static int
838add9520fSAndreas Jaekel zev_debug_info(int fd)
839add9520fSAndreas Jaekel {
840add9520fSAndreas Jaekel 	zev_ioctl_debug_info_t di;
841add9520fSAndreas Jaekel 
842add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
843add9520fSAndreas Jaekel 		perror("getting zev debug info failed");
844add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
845add9520fSAndreas Jaekel 	}
846add9520fSAndreas Jaekel 
847add9520fSAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
848205ed6bfSAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
849205ed6bfSAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
850205ed6bfSAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
851add9520fSAndreas Jaekel 	return 0;
852add9520fSAndreas Jaekel }
853add9520fSAndreas Jaekel 
854add9520fSAndreas Jaekel static int
855888fea18SAndreas Jaekel zev_mark(int fd, char *arg)
856888fea18SAndreas Jaekel {
857888fea18SAndreas Jaekel 	zev_ioctl_mark_t *mark;
858888fea18SAndreas Jaekel 	uint64_t guid;
859888fea18SAndreas Jaekel 	int len;
860888fea18SAndreas Jaekel 	char *p;
861888fea18SAndreas Jaekel 
862888fea18SAndreas Jaekel 	p = strchr(arg, ':');
863888fea18SAndreas Jaekel 	if (!p) {
864888fea18SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
865888fea18SAndreas Jaekel 		        "e.g. '123:hello'\n");
866888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
867888fea18SAndreas Jaekel 	}
868888fea18SAndreas Jaekel 	*p = '\n';
869888fea18SAndreas Jaekel 	p++;
870888fea18SAndreas Jaekel 
871888fea18SAndreas Jaekel 	errno = 0;
872add9520fSAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
873888fea18SAndreas Jaekel 	if (errno) {
874888fea18SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
875888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
876888fea18SAndreas Jaekel 	}
877888fea18SAndreas Jaekel 
878888fea18SAndreas Jaekel 	len = strlen(p);
879888fea18SAndreas Jaekel 
880888fea18SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
881888fea18SAndreas Jaekel 	if (!mark) {
882888fea18SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
883888fea18SAndreas Jaekel 		        strerror(errno));
884888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
885888fea18SAndreas Jaekel 	}
886888fea18SAndreas Jaekel 	mark->zev_guid = guid;
887888fea18SAndreas Jaekel 	mark->zev_mark_id = 0;
888888fea18SAndreas Jaekel 	mark->zev_payload_len = len;
889888fea18SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
890888fea18SAndreas Jaekel 
891888fea18SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
892888fea18SAndreas Jaekel 		perror("queueing mark failed");
893888fea18SAndreas Jaekel 		return (EXIT_FAILURE);
894888fea18SAndreas Jaekel 	}
895888fea18SAndreas Jaekel 
896888fea18SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
897888fea18SAndreas Jaekel 	return (0);
898888fea18SAndreas Jaekel }
899888fea18SAndreas Jaekel 
900add9520fSAndreas Jaekel static int
901add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
902add9520fSAndreas Jaekel {
903add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
904add9520fSAndreas Jaekel 
9056a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9066a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
907add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
908add9520fSAndreas Jaekel 		return EXIT_FAILURE;
909add9520fSAndreas Jaekel 	}
9106a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
911add9520fSAndreas Jaekel 
912add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
913add9520fSAndreas Jaekel 		perror("getting queue properties failed");
914add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
915add9520fSAndreas Jaekel 	}
916add9520fSAndreas Jaekel 	if (block) {
917add9520fSAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
918add9520fSAndreas Jaekel 	} else {
919add9520fSAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
920add9520fSAndreas Jaekel 	}
921add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
922add9520fSAndreas Jaekel 		perror("setting queue properties failed");
923add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
924add9520fSAndreas Jaekel 	}
925add9520fSAndreas Jaekel 	return (0);
926add9520fSAndreas Jaekel }
927add9520fSAndreas Jaekel 
928add9520fSAndreas Jaekel static int
929add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
930add9520fSAndreas Jaekel {
931add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
932add9520fSAndreas Jaekel 
933add9520fSAndreas Jaekel 	if (!len) {
934add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
935add9520fSAndreas Jaekel 		return EXIT_FAILURE;
936add9520fSAndreas Jaekel 	}
937add9520fSAndreas Jaekel 
9386a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9396a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
940add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
941add9520fSAndreas Jaekel 		return EXIT_FAILURE;
942add9520fSAndreas Jaekel 	}
9436a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
944add9520fSAndreas Jaekel 
945add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
946add9520fSAndreas Jaekel 		perror("getting queue properties failed");
947add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
948add9520fSAndreas Jaekel 	}
949add9520fSAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
950add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
951add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
952add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
953add9520fSAndreas Jaekel 	}
954add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
955add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
956add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
957add9520fSAndreas Jaekel 	}
958add9520fSAndreas Jaekel 
959add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
960add9520fSAndreas Jaekel 		perror("setting queue properties failed");
961add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
962add9520fSAndreas Jaekel 	}
963add9520fSAndreas Jaekel 	return (0);
964add9520fSAndreas Jaekel }
965add9520fSAndreas Jaekel 
966add9520fSAndreas Jaekel static int
967add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
968add9520fSAndreas Jaekel {
969add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
970add9520fSAndreas Jaekel 
971add9520fSAndreas Jaekel 	if (!len) {
972add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
973add9520fSAndreas Jaekel 		return EXIT_FAILURE;
974add9520fSAndreas Jaekel 	}
975add9520fSAndreas Jaekel 
9766a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9776a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
978add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
979add9520fSAndreas Jaekel 		return EXIT_FAILURE;
980add9520fSAndreas Jaekel 	}
9816a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
982add9520fSAndreas Jaekel 
983add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
984add9520fSAndreas Jaekel 		perror("getting queue properties failed");
985add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
986add9520fSAndreas Jaekel 	}
987add9520fSAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
988add9520fSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
989add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
990add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
991add9520fSAndreas Jaekel 	}
9926a6a51eeSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
993add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
994add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
995add9520fSAndreas Jaekel 	}
996add9520fSAndreas Jaekel 
997add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
998add9520fSAndreas Jaekel 		perror("setting queue properties failed");
999add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1000add9520fSAndreas Jaekel 	}
1001add9520fSAndreas Jaekel 	return (0);
1002add9520fSAndreas Jaekel }
1003add9520fSAndreas Jaekel 
1004add9520fSAndreas Jaekel static int
1005add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg)
1006add9520fSAndreas Jaekel {
1007add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1008add9520fSAndreas Jaekel 
10096a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
10106a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
1011add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
1012add9520fSAndreas Jaekel 		return EXIT_FAILURE;
1013add9520fSAndreas Jaekel 	}
10146a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
1015add9520fSAndreas Jaekel 
1016add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1017add9520fSAndreas Jaekel 		perror("getting queue properties failed");
1018add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1019add9520fSAndreas Jaekel 	}
1020add9520fSAndreas Jaekel 
1021add9520fSAndreas Jaekel 	printf("queue        : %s\n", arg);
1022add9520fSAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1023add9520fSAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1024add9520fSAndreas Jaekel 	printf("persistent   : %s\n",
1025add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1026add9520fSAndreas Jaekel 	printf("blocking     : %s\n",
1027add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1028add9520fSAndreas Jaekel 
1029add9520fSAndreas Jaekel 	return (0);
1030add9520fSAndreas Jaekel }
1031add9520fSAndreas Jaekel 
1032add9520fSAndreas Jaekel static int
1033add9520fSAndreas Jaekel zev_list_queues(int fd)
1034add9520fSAndreas Jaekel {
1035add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1036add9520fSAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1037add9520fSAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1038add9520fSAndreas Jaekel 	uint64_t	i;
1039add9520fSAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1040add9520fSAndreas Jaekel 
1041add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1042add9520fSAndreas Jaekel 		perror("getting queue list failed");
1043add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1044add9520fSAndreas Jaekel 	}
1045add9520fSAndreas Jaekel 
1046add9520fSAndreas Jaekel 	printf("Name                                     Size       "
1047add9520fSAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
1048add9520fSAndreas Jaekel 
1049add9520fSAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1050add9520fSAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1051add9520fSAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1052add9520fSAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1053add9520fSAndreas Jaekel 
10546a6a51eeSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
10556a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
10566a6a51eeSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
10576a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1058add9520fSAndreas Jaekel 
1059add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1060add9520fSAndreas Jaekel 			if (errno == ENOENT)
1061add9520fSAndreas Jaekel 				continue;
1062add9520fSAndreas Jaekel 			perror("getting queue properties failed");
1063add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1064add9520fSAndreas Jaekel 		}
1065add9520fSAndreas Jaekel 
10666a6a51eeSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
10676a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
10686a6a51eeSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
10696a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1070add9520fSAndreas Jaekel 
1071add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1072add9520fSAndreas Jaekel 			if (errno == ENOENT)
1073add9520fSAndreas Jaekel 				continue;
1074add9520fSAndreas Jaekel 			perror("getting statistics data failed");
1075add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1076add9520fSAndreas Jaekel 		}
1077add9520fSAndreas Jaekel 
1078add9520fSAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
1079add9520fSAndreas Jaekel 		       " %-3s %-3s\n",
1080add9520fSAndreas Jaekel 			name,
1081add9520fSAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1082add9520fSAndreas Jaekel 			gqp.zev_max_queue_len,
1083add9520fSAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
1084add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1085add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1086add9520fSAndreas Jaekel 				 "yes" : "no");
1087add9520fSAndreas Jaekel 	}
1088add9520fSAndreas Jaekel 
1089add9520fSAndreas Jaekel 	return (0);
1090add9520fSAndreas Jaekel }
1091add9520fSAndreas Jaekel 
109242110aacSAndreas Jaekel static int
109342110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename)
109442110aacSAndreas Jaekel {
109542110aacSAndreas Jaekel 	int fd;
109642110aacSAndreas Jaekel 	offset_t off;
109742110aacSAndreas Jaekel 	offset_t data;
109842110aacSAndreas Jaekel 	zev_sig_t *sig;
109942110aacSAndreas Jaekel 	char *buf;
110042110aacSAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
110142110aacSAndreas Jaekel 	int i;
110242110aacSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
110342110aacSAndreas Jaekel 	int buf_size;
110442110aacSAndreas Jaekel 
110542110aacSAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
110642110aacSAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
110742110aacSAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
110842110aacSAndreas Jaekel 	if (!buf) {
110942110aacSAndreas Jaekel 		perror("can't allocate checksum buffer");
111042110aacSAndreas Jaekel 		return (EXIT_FAILURE);
111142110aacSAndreas Jaekel 	}
111242110aacSAndreas Jaekel 
111342110aacSAndreas Jaekel 	fd = open(filename, O_RDONLY);
111442110aacSAndreas Jaekel 	if (fd < 0) {
111542110aacSAndreas Jaekel 		perror("can't open file");
111642110aacSAndreas Jaekel 		return (EXIT_FAILURE);
111742110aacSAndreas Jaekel 	}
111842110aacSAndreas Jaekel 
111942110aacSAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
112042110aacSAndreas Jaekel 	gs->zev_fd = fd;
112142110aacSAndreas Jaekel 	gs->zev_bufsize = buf_size;
112242110aacSAndreas Jaekel 
112342110aacSAndreas Jaekel 	off = 0;
112442110aacSAndreas Jaekel 	data = 0;
112542110aacSAndreas Jaekel 	while (1) {
112642110aacSAndreas Jaekel 		errno = 0;
112742110aacSAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
112842110aacSAndreas Jaekel 		if (data < 0) {
112942110aacSAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
113042110aacSAndreas Jaekel 				break;
113142110aacSAndreas Jaekel 			perror("llseek failed");
113242110aacSAndreas Jaekel 			goto err;
113342110aacSAndreas Jaekel 		}
113442110aacSAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
113542110aacSAndreas Jaekel 		off = data + ZEV_L1_SIZE;
113642110aacSAndreas Jaekel 
113742110aacSAndreas Jaekel 		gs->zev_offset = data;
113842110aacSAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
113942110aacSAndreas Jaekel 
114042110aacSAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
114142110aacSAndreas Jaekel 			perror("ioctl to get signatures failed");
114242110aacSAndreas Jaekel 			goto err;
114342110aacSAndreas Jaekel 		}
114442110aacSAndreas Jaekel 
114542110aacSAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
114642110aacSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
114742110aacSAndreas Jaekel 			sig += i;
114842110aacSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
114942110aacSAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
115042110aacSAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
115142110aacSAndreas Jaekel 		}
115242110aacSAndreas Jaekel 	}
115342110aacSAndreas Jaekel 
115442110aacSAndreas Jaekel 	free(buf);
115542110aacSAndreas Jaekel 	close(fd);
115642110aacSAndreas Jaekel 	return 0;
115742110aacSAndreas Jaekel err:
115842110aacSAndreas Jaekel 	free(buf);
115942110aacSAndreas Jaekel 	close(fd);
116042110aacSAndreas Jaekel 	return (EXIT_FAILURE);
116142110aacSAndreas Jaekel }
116242110aacSAndreas Jaekel 
1163a18c35b9SAndreas Jaekel int
1164a18c35b9SAndreas Jaekel main(int argc, char **argv)
1165a18c35b9SAndreas Jaekel {
1166a18c35b9SAndreas Jaekel 	int fd;
1167a18c35b9SAndreas Jaekel 	int c;
1168a18c35b9SAndreas Jaekel 	extern char *optarg;
11696a6a51eeSAndreas Jaekel 	int create_tmp_queue = 1;
11706a6a51eeSAndreas Jaekel 	char buf[MAXPATHLEN];
1171a18c35b9SAndreas Jaekel 
1172a18c35b9SAndreas Jaekel 	/* open device */
1173a18c35b9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
1174a18c35b9SAndreas Jaekel 	if (fd < 0) {
1175a18c35b9SAndreas Jaekel 		perror("opening zev device failed");
1176a18c35b9SAndreas Jaekel 		return EXIT_FAILURE;
1177a18c35b9SAndreas Jaekel 	}
11786a6a51eeSAndreas Jaekel 	while ((c = getopt(argc, argv,
117916ff6b2fSAndreas Jaekel 	                   "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){
1180a18c35b9SAndreas Jaekel 		switch(c) {
118116ff6b2fSAndreas Jaekel 		case 'g':
118216ff6b2fSAndreas Jaekel 			grep_friendly++;
118316ff6b2fSAndreas Jaekel 			verbose++;
118416ff6b2fSAndreas Jaekel 			break;
1185205ed6bfSAndreas Jaekel 		case 'v':
1186205ed6bfSAndreas Jaekel 			verbose++;
1187205ed6bfSAndreas Jaekel 			break;
1188a18c35b9SAndreas Jaekel 		case 's':
1189add9520fSAndreas Jaekel 			return zev_statistics(fd);
1190a18c35b9SAndreas Jaekel 		case 'p':
11916a6a51eeSAndreas Jaekel 			return zev_poll_events(fd, create_tmp_queue);
119242110aacSAndreas Jaekel 		case 'c':
119342110aacSAndreas Jaekel 			return zev_checksum(fd, optarg);
1194add9520fSAndreas Jaekel 		case 'D':
1195add9520fSAndreas Jaekel 			return zev_debug_info(fd);
1196a18c35b9SAndreas Jaekel 		case 'd':
1197add9520fSAndreas Jaekel 			close(fd);
1198a18c35b9SAndreas Jaekel 			zev_device = optarg;
1199add9520fSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1200add9520fSAndreas Jaekel 			if (fd < 0) {
1201add9520fSAndreas Jaekel 				perror("opening zev device failed");
1202add9520fSAndreas Jaekel 				return EXIT_FAILURE;
1203add9520fSAndreas Jaekel 			}
12046a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
12056a6a51eeSAndreas Jaekel 			break;
12066a6a51eeSAndreas Jaekel 		case 'q':
12076a6a51eeSAndreas Jaekel 			snprintf(buf, sizeof(buf),
12086a6a51eeSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
12096a6a51eeSAndreas Jaekel 			close(fd);
12106a6a51eeSAndreas Jaekel 			zev_device = buf;
12116a6a51eeSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
12126a6a51eeSAndreas Jaekel 			if (fd < 0) {
12136a6a51eeSAndreas Jaekel 				perror("opening zev device failed");
12146a6a51eeSAndreas Jaekel 				return EXIT_FAILURE;
12156a6a51eeSAndreas Jaekel 			}
12166a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
1217a18c35b9SAndreas Jaekel 			break;
1218add9520fSAndreas Jaekel 		case 'l':
1219add9520fSAndreas Jaekel 			return zev_list_queues(fd);
1220add9520fSAndreas Jaekel 		case 'Q':
1221add9520fSAndreas Jaekel 			return zev_set_global_max_queue_len(fd, optarg);
12226a6a51eeSAndreas Jaekel 		case 'L':
1223add9520fSAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg, argv[optind]);
1224fec460f8SAndreas Jaekel 		case 't':
1225add9520fSAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg,
1226add9520fSAndreas Jaekel 			                                     argv[optind]);
1227a18c35b9SAndreas Jaekel 		case 'm':
1228a18c35b9SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
1229a18c35b9SAndreas Jaekel 		case 'M':
1230a18c35b9SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
1231888fea18SAndreas Jaekel 		case 'k':
1232888fea18SAndreas Jaekel 			return zev_mark(fd, optarg);
1233add9520fSAndreas Jaekel 		case 'a':
12346a6a51eeSAndreas Jaekel 			return zev_add_queue(fd, optarg, 0);
12356a6a51eeSAndreas Jaekel 		case 'A':
12366a6a51eeSAndreas Jaekel 			return zev_add_queue(fd, optarg, 1);
1237add9520fSAndreas Jaekel 		case 'r':
1238add9520fSAndreas Jaekel 			return zev_remove_queue(fd, optarg);
1239add9520fSAndreas Jaekel 		case 'b':
1240add9520fSAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 0);
1241add9520fSAndreas Jaekel 		case 'B':
1242add9520fSAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 1);
1243add9520fSAndreas Jaekel 		case 'P':
1244add9520fSAndreas Jaekel 			return zev_queue_properties(fd, optarg);
1245a18c35b9SAndreas Jaekel 		case 'h':
1246a18c35b9SAndreas Jaekel 		case '?':
1247a18c35b9SAndreas Jaekel 		default:
1248a18c35b9SAndreas Jaekel 			usage(argv[0]);
1249a18c35b9SAndreas Jaekel 		}
1250a18c35b9SAndreas Jaekel 	}
1251a18c35b9SAndreas Jaekel 	usage(argv[0]);
1252a18c35b9SAndreas Jaekel 	close(fd);
1253add9520fSAndreas Jaekel 	return EXIT_FAILURE;
1254a18c35b9SAndreas Jaekel }
1255a18c35b9SAndreas Jaekel 
1256