xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision 16ff6b2f0d024ab5ad7ca87a61f8a9fc9f19a00b)
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>
11*16ff6b2fSAndreas 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[] = {
18*16ff6b2fSAndreas Jaekel 	"ERROR",
19*16ff6b2fSAndreas Jaekel 	"MARK",
20*16ff6b2fSAndreas Jaekel 	"ZFS_MOUNT",
21*16ff6b2fSAndreas Jaekel 	"ZFS_UMOUNT",
22*16ff6b2fSAndreas Jaekel 	"ZVOL_WRITE",
23*16ff6b2fSAndreas Jaekel 	"ZVOL_TRUNCATE",
24*16ff6b2fSAndreas Jaekel 	"ZNODE_CLOSE_AFTER_UPDATE",
25*16ff6b2fSAndreas Jaekel 	"ZNODE_CREATE",
26*16ff6b2fSAndreas Jaekel 	"ZNODE_MKDIR",
27*16ff6b2fSAndreas Jaekel 	"ZNODE_MAKE_XATTR_DIR",
28*16ff6b2fSAndreas Jaekel 	"ZNODE_REMOVE",
29*16ff6b2fSAndreas Jaekel 	"ZNODE_RMDIR",
30*16ff6b2fSAndreas Jaekel 	"ZNODE_LINK",
31*16ff6b2fSAndreas Jaekel 	"ZNODE_SYMLINK",
32*16ff6b2fSAndreas Jaekel 	"ZNODE_RENAME",
33*16ff6b2fSAndreas Jaekel 	"ZNODE_WRITE",
34*16ff6b2fSAndreas Jaekel 	"ZNODE_TRUNCATE",
35*16ff6b2fSAndreas Jaekel 	"ZNODE_SETATTR",
36*16ff6b2fSAndreas Jaekel 	"ZNODE_ACL",
37aafc540fSAndreas Jaekel 	NULL
38aafc540fSAndreas Jaekel };
39aafc540fSAndreas Jaekel 
40205ed6bfSAndreas Jaekel static int verbose = 0;
41*16ff6b2fSAndreas Jaekel static int grep_friendly = 0;
42*16ff6b2fSAndreas Jaekel 
43*16ff6b2fSAndreas Jaekel static void
44*16ff6b2fSAndreas Jaekel zpf(char *fmt, ...)
45*16ff6b2fSAndreas Jaekel {
46*16ff6b2fSAndreas Jaekel 	va_list	ap;
47*16ff6b2fSAndreas Jaekel 
48*16ff6b2fSAndreas Jaekel 	va_start(ap, fmt);
49*16ff6b2fSAndreas Jaekel 	vprintf(fmt, ap);
50*16ff6b2fSAndreas Jaekel 	va_end(ap);
51*16ff6b2fSAndreas Jaekel 	if (grep_friendly) {
52*16ff6b2fSAndreas Jaekel 		printf(" ");
53*16ff6b2fSAndreas Jaekel 	} else {
54*16ff6b2fSAndreas Jaekel 		printf("\n");
55*16ff6b2fSAndreas Jaekel 	}
56*16ff6b2fSAndreas Jaekel }
57*16ff6b2fSAndreas Jaekel 
58*16ff6b2fSAndreas Jaekel static void
59*16ff6b2fSAndreas Jaekel znl(void)
60*16ff6b2fSAndreas Jaekel {
61*16ff6b2fSAndreas Jaekel 	if (grep_friendly)
62*16ff6b2fSAndreas Jaekel 		printf("\n");
63*16ff6b2fSAndreas Jaekel }
64205ed6bfSAndreas Jaekel 
65add9520fSAndreas Jaekel static int
66a18c35b9SAndreas Jaekel zev_statistics(int fd)
67a18c35b9SAndreas Jaekel {
68a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
69add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
70a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
71add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
72a18c35b9SAndreas Jaekel 	}
73a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
74a18c35b9SAndreas Jaekel 
75a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
76a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
77a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
78a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
79a18c35b9SAndreas Jaekel 
80add9520fSAndreas Jaekel 	printf("    discarded events        : %lu\n",
81add9520fSAndreas Jaekel 	    zs.zev_cnt_discarded_events);
82add9520fSAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
83add9520fSAndreas Jaekel 
84a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
85a18c35b9SAndreas Jaekel 
86a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
87a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
88a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
89a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
90a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
91a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
92a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
93a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
94a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
95a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
96a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
97a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
98a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
99a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
100a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
101a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
102a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
103add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
104a18c35b9SAndreas Jaekel }
105a18c35b9SAndreas Jaekel 
106a18c35b9SAndreas Jaekel static void
107*16ff6b2fSAndreas Jaekel zev_print_inode_info(char *name, zev_inode_info_t *info)
108*16ff6b2fSAndreas Jaekel {
109*16ff6b2fSAndreas Jaekel 	zpf("  %s.inode: %llu", name, info->ino);
110*16ff6b2fSAndreas Jaekel 	zpf("  %s.gen: %llu", name, info->gen);
111*16ff6b2fSAndreas Jaekel 	zpf("  %s.mtime: %llu", name, info->mtime);
112*16ff6b2fSAndreas Jaekel 	zpf("  %s.ctime: %llu", name, info->ctime);
113*16ff6b2fSAndreas Jaekel 	zpf("  %s.size: %llu", name, info->size);
114*16ff6b2fSAndreas Jaekel 	zpf("  %s.mode: %llo", name, info->mode);
115*16ff6b2fSAndreas Jaekel 	zpf("  %s.links: %llu", name, info->links);
116*16ff6b2fSAndreas Jaekel 	zpf("  %s.type: %lu", name, info->type);
117*16ff6b2fSAndreas Jaekel 	zpf("  %s.flags: %lu", name, info->flags);
118*16ff6b2fSAndreas Jaekel }
119*16ff6b2fSAndreas Jaekel 
120*16ff6b2fSAndreas Jaekel static void
121*16ff6b2fSAndreas Jaekel zev_print_mark_payload(zev_mark_t *rec)
122*16ff6b2fSAndreas Jaekel {
123*16ff6b2fSAndreas Jaekel 	int i;
124*16ff6b2fSAndreas Jaekel 	int j;
125*16ff6b2fSAndreas Jaekel 	uint8_t *p;
126*16ff6b2fSAndreas Jaekel 	char c;
127*16ff6b2fSAndreas Jaekel 
128*16ff6b2fSAndreas Jaekel 	zpf("  payload:");
129*16ff6b2fSAndreas Jaekel 	p = (uint8_t *)ZEV_PAYLOAD(rec);
130*16ff6b2fSAndreas Jaekel 	for (i=0; i<rec->payload_len; i+=16) {
131*16ff6b2fSAndreas Jaekel 		printf("  ");
132*16ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
133*16ff6b2fSAndreas Jaekel 			printf("%02x ", p[j]);
134*16ff6b2fSAndreas Jaekel 			if (j == i + 7)
135*16ff6b2fSAndreas Jaekel 				printf(" ");
136*16ff6b2fSAndreas Jaekel 		}
137*16ff6b2fSAndreas Jaekel 		if (grep_friendly)
138*16ff6b2fSAndreas Jaekel 			continue;
139*16ff6b2fSAndreas Jaekel 		for (; j<i+16; j++) {
140*16ff6b2fSAndreas Jaekel 			printf("   ");
141*16ff6b2fSAndreas Jaekel 			if (j == i + 7)
142*16ff6b2fSAndreas Jaekel 				printf(" ");
143*16ff6b2fSAndreas Jaekel 		}
144*16ff6b2fSAndreas Jaekel 		printf("    ");
145*16ff6b2fSAndreas Jaekel 		for (j=i; j<rec->payload_len && j<i+16; j++) {
146*16ff6b2fSAndreas Jaekel 			c = '.';
147*16ff6b2fSAndreas Jaekel 			if (p[j] >= ' ' && p[j] <= '~')
148*16ff6b2fSAndreas Jaekel 				c = p[j];
149*16ff6b2fSAndreas Jaekel 			printf("%c", c);
150*16ff6b2fSAndreas Jaekel 			if (j == i + 7)
151*16ff6b2fSAndreas Jaekel 				printf(" ");
152*16ff6b2fSAndreas Jaekel 		}
153*16ff6b2fSAndreas Jaekel 		printf("\n");
154*16ff6b2fSAndreas Jaekel 	}
155*16ff6b2fSAndreas Jaekel }
156*16ff6b2fSAndreas Jaekel 
157*16ff6b2fSAndreas Jaekel static void
158f2dd45e5SAndreas Jaekel zev_print_error(char *buf)
159f2dd45e5SAndreas Jaekel {
160f2dd45e5SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
161f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
162f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
163f2dd45e5SAndreas Jaekel 
164*16ff6b2fSAndreas Jaekel 	if (verbose) {
165*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
166*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
167*16ff6b2fSAndreas Jaekel 		zpf("  failed.op: %s",
168*16ff6b2fSAndreas Jaekel 		    zev_op_name[rec->failed_op - ZEV_OP_MIN]);
169*16ff6b2fSAndreas Jaekel 		zpf("  message: %s", ZEV_ERRSTR(rec));
170*16ff6b2fSAndreas Jaekel 		znl();
171*16ff6b2fSAndreas Jaekel 	} else {
172f2dd45e5SAndreas Jaekel 		printf("%s %s: failed_op=%s msg=%s\n",
173f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
174*16ff6b2fSAndreas Jaekel 		       zev_op_name[rec->failed_op - ZEV_OP_MIN],
175*16ff6b2fSAndreas Jaekel 		       ZEV_ERRSTR(rec));
176*16ff6b2fSAndreas Jaekel 	}
177f2dd45e5SAndreas Jaekel }
178f2dd45e5SAndreas Jaekel 
179f2dd45e5SAndreas Jaekel static void
180888fea18SAndreas Jaekel zev_print_mark(char *buf)
181888fea18SAndreas Jaekel {
182888fea18SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
183888fea18SAndreas Jaekel 	time_t op_time = rec->op_time;
184888fea18SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
185888fea18SAndreas Jaekel 
186*16ff6b2fSAndreas Jaekel 	if (verbose) {
187*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
188*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
189*16ff6b2fSAndreas Jaekel 		zpf("  mark.id: %llu", rec->mark_id);
190*16ff6b2fSAndreas Jaekel 		zpf("  payload.len: %llu", rec->payload_len);
191*16ff6b2fSAndreas Jaekel 		if (rec->payload_len)
192*16ff6b2fSAndreas Jaekel 			zev_print_mark_payload(rec);
193*16ff6b2fSAndreas Jaekel 		znl();
194*16ff6b2fSAndreas Jaekel 	} else {
195888fea18SAndreas Jaekel 		printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
196*16ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid,
197*16ff6b2fSAndreas Jaekel 		       rec->mark_id, rec->payload_len);
198*16ff6b2fSAndreas Jaekel 	}
199888fea18SAndreas Jaekel }
200888fea18SAndreas Jaekel 
201888fea18SAndreas Jaekel static void
202f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf)
203f2dd45e5SAndreas Jaekel {
204f2dd45e5SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
205f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
206f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
207f2dd45e5SAndreas Jaekel 
208*16ff6b2fSAndreas Jaekel 	if (verbose) {
209*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
210*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
211*16ff6b2fSAndreas Jaekel 		zpf("  dataset: %s", ZEV_DATASET(rec));
212*16ff6b2fSAndreas Jaekel 		zpf("  mountpoint: %s", ZEV_MOUNTPOINT(rec));
213*16ff6b2fSAndreas Jaekel 		zpf("  remount: %s", rec->remount ? "true" : "false");
214*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("root", &rec->root);
215*16ff6b2fSAndreas Jaekel 		znl();
216*16ff6b2fSAndreas Jaekel 	} else {
217*16ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu remount=%s dataset='%s' "
218*16ff6b2fSAndreas Jaekel 		       "mountpoint='%s'\n",
219f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
220f2dd45e5SAndreas Jaekel 		       rec->guid,
221f2dd45e5SAndreas Jaekel 		       rec->remount ? "true" : "false",
222f2dd45e5SAndreas Jaekel 		       ZEV_DATASET(rec),
223f2dd45e5SAndreas Jaekel 		       ZEV_MOUNTPOINT(rec));
224f2dd45e5SAndreas Jaekel 	}
225*16ff6b2fSAndreas Jaekel }
226f2dd45e5SAndreas Jaekel 
227f2dd45e5SAndreas Jaekel static void
228f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf)
229f2dd45e5SAndreas Jaekel {
230f2dd45e5SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
231f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
232f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
233f2dd45e5SAndreas Jaekel 
234*16ff6b2fSAndreas Jaekel 	if (verbose) {
235*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
236*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
237*16ff6b2fSAndreas Jaekel 		znl();
238*16ff6b2fSAndreas Jaekel 	} else {
239f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu\n",
240f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
241f2dd45e5SAndreas Jaekel 		       rec->guid);
242f2dd45e5SAndreas Jaekel 	}
243*16ff6b2fSAndreas Jaekel }
244f2dd45e5SAndreas Jaekel 
245f2dd45e5SAndreas Jaekel static void
246f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf)
247f2dd45e5SAndreas Jaekel {
248f2dd45e5SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
249f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
250f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
251f2dd45e5SAndreas Jaekel 
252*16ff6b2fSAndreas Jaekel 	if (verbose) {
253*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
254*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
255*16ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
256*16ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
257*16ff6b2fSAndreas Jaekel 		znl();
258*16ff6b2fSAndreas Jaekel 	} else {
259f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu offset=%llu length=%llu\n",
260f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
261f2dd45e5SAndreas Jaekel 		       rec->guid,
262f2dd45e5SAndreas Jaekel 		       rec->offset,
263f2dd45e5SAndreas Jaekel 		       rec->length);
264f2dd45e5SAndreas Jaekel 	}
265*16ff6b2fSAndreas Jaekel }
266f2dd45e5SAndreas Jaekel 
267f2dd45e5SAndreas Jaekel static void
268f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf)
269f2dd45e5SAndreas Jaekel {
270f2dd45e5SAndreas Jaekel 	zev_print_zvol_truncate(buf);
271f2dd45e5SAndreas Jaekel }
272f2dd45e5SAndreas Jaekel 
273f2dd45e5SAndreas Jaekel static void
274f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
275f2dd45e5SAndreas Jaekel {
276f2dd45e5SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
277f2dd45e5SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
278f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
279f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
280f2dd45e5SAndreas Jaekel 
281*16ff6b2fSAndreas Jaekel 	if (verbose) {
282*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
283*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
284*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
285*16ff6b2fSAndreas Jaekel 		znl();
286*16ff6b2fSAndreas Jaekel 	} else {
287f2dd45e5SAndreas Jaekel 		printf("%s %s: guid=%llu file=%llu.%llu\n",
288f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
289f2dd45e5SAndreas Jaekel 		       rec->guid,
290f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen);
291f2dd45e5SAndreas Jaekel 	}
292*16ff6b2fSAndreas Jaekel }
293f2dd45e5SAndreas Jaekel 
294f2dd45e5SAndreas Jaekel static void
295f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf)
296f2dd45e5SAndreas Jaekel {
297f2dd45e5SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
298f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
299f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
300f2dd45e5SAndreas Jaekel 
301*16ff6b2fSAndreas Jaekel 	if (verbose) {
302*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
303*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
304*16ff6b2fSAndreas Jaekel 		zpf("  name: '%s'", ZEV_NAME(rec));
305*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("parent", &rec->file);
306*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
307*16ff6b2fSAndreas Jaekel 		znl();
308*16ff6b2fSAndreas Jaekel 	} else {
30935d4e8ddSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
31035d4e8ddSAndreas Jaekel 		       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
311f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
312f2dd45e5SAndreas Jaekel 		       rec->guid,
313f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
314f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
31535d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->parent.mtime,
316f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
317f2dd45e5SAndreas Jaekel 	}
318*16ff6b2fSAndreas Jaekel }
319f2dd45e5SAndreas Jaekel 
320f2dd45e5SAndreas Jaekel static void
321f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf)
322f2dd45e5SAndreas Jaekel {
323f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
324f2dd45e5SAndreas Jaekel }
325f2dd45e5SAndreas Jaekel 
326f2dd45e5SAndreas Jaekel static void
327f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
328f2dd45e5SAndreas Jaekel {
329f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
330f2dd45e5SAndreas Jaekel }
331f2dd45e5SAndreas Jaekel 
332f2dd45e5SAndreas Jaekel static void
333f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf)
334f2dd45e5SAndreas Jaekel {
335f2dd45e5SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
336f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
337f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
338f2dd45e5SAndreas Jaekel 
339*16ff6b2fSAndreas Jaekel 	if (verbose) {
340*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
341*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
342*16ff6b2fSAndreas Jaekel 		zpf("  file.name: '%s'", ZEV_NAME(rec));
343*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
344*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("parent", &rec->file);
345*16ff6b2fSAndreas Jaekel 		znl();
346*16ff6b2fSAndreas Jaekel 	} else {
347*16ff6b2fSAndreas Jaekel 		printf("%s %s: guid=%llu parent=%llu.%llu "
348*16ff6b2fSAndreas Jaekel 		       "file.mtime=%llu name='%s'\n",
349f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
350f2dd45e5SAndreas Jaekel 		       rec->guid,
351f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
35297dcf88dSAndreas Jaekel 		       rec->file.mtime,
353f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
354f2dd45e5SAndreas Jaekel 	}
355*16ff6b2fSAndreas Jaekel }
356f2dd45e5SAndreas Jaekel 
357f2dd45e5SAndreas Jaekel static void
358f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf)
359f2dd45e5SAndreas Jaekel {
360f2dd45e5SAndreas Jaekel 	zev_print_znode_remove(buf);
361f2dd45e5SAndreas Jaekel }
362f2dd45e5SAndreas Jaekel 
363f2dd45e5SAndreas Jaekel static void
364f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf)
365f2dd45e5SAndreas Jaekel {
366f2dd45e5SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
367f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
368f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
369f2dd45e5SAndreas Jaekel 
370*16ff6b2fSAndreas Jaekel 	if (verbose) {
371*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
372*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
373*16ff6b2fSAndreas Jaekel 		zpf("  link.name: '%s'", ZEV_NAME(rec));
374*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
375*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("parent", &rec->file);
376*16ff6b2fSAndreas Jaekel 		znl();
377*16ff6b2fSAndreas Jaekel 	} else {
378a01b300aSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
379a01b300aSAndreas Jaekel 		       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
380f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
381f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
382f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
383a01b300aSAndreas Jaekel 		       rec->file.ctime, rec->parent.ctime,
384f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec));
385*16ff6b2fSAndreas Jaekel 	}
386f2dd45e5SAndreas Jaekel }
387f2dd45e5SAndreas Jaekel 
388f2dd45e5SAndreas Jaekel static void
389f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf)
390f2dd45e5SAndreas Jaekel {
391f2dd45e5SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
392f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
393f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
394f2dd45e5SAndreas Jaekel 
395*16ff6b2fSAndreas Jaekel 	if (verbose) {
396*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
397*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
398*16ff6b2fSAndreas Jaekel 		zpf("  symlink.name: '%s'", ZEV_NAME(rec));
399*16ff6b2fSAndreas Jaekel 		zpf("  symlink.link: '%s'", ZEV_LINK(rec));
400*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
401*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("parent", &rec->file);
402*16ff6b2fSAndreas Jaekel 		znl();
403*16ff6b2fSAndreas Jaekel 	} else {
404*16ff6b2fSAndreas Jaekel 		printf("%s %s: parent=%llu.%llu file=%llu.%llu "
405*16ff6b2fSAndreas Jaekel 		       "name='%s' link='%s'\n",
406f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
407f2dd45e5SAndreas Jaekel 		       rec->parent.ino, rec->parent.gen,
408f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
409f2dd45e5SAndreas Jaekel 		       ZEV_NAME(rec),
410f2dd45e5SAndreas Jaekel 		       ZEV_LINK(rec));
411f2dd45e5SAndreas Jaekel 	}
412*16ff6b2fSAndreas Jaekel }
413f2dd45e5SAndreas Jaekel 
414f2dd45e5SAndreas Jaekel static void
415f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf)
416f2dd45e5SAndreas Jaekel {
417f2dd45e5SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
418f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
419f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
420f2dd45e5SAndreas Jaekel 
421*16ff6b2fSAndreas Jaekel 	if (verbose) {
422*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
423*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
424*16ff6b2fSAndreas Jaekel 		zpf("  file.srcname: '%s'", ZEV_SRCNAME(rec));
425*16ff6b2fSAndreas Jaekel 		zpf("  file.dstname: '%s'", ZEV_DSTNAME(rec));
426*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
427*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("srcdir", &rec->srcdir);
428*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("dstdir", &rec->dstdir);
429*16ff6b2fSAndreas Jaekel 		znl();
430*16ff6b2fSAndreas Jaekel 	} else {
431*16ff6b2fSAndreas Jaekel 		printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu "
432*16ff6b2fSAndreas Jaekel 		       "file=%llu.%llu file.mtime=%llu, file.ctime=%llu, "
433*16ff6b2fSAndreas Jaekel 		       "srcdir.mtime=%llu, srcdir.ctime=%llu, "
434*16ff6b2fSAndreas Jaekel 		       "dstdir.mtime=%llu, dstdir.ctime=%llu, "
435f2dd45e5SAndreas Jaekel 		       "srcname='%s' dstname='%s'\n",
436f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
437f2dd45e5SAndreas Jaekel 		       rec->srcdir.ino, rec->srcdir.gen,
438f2dd45e5SAndreas Jaekel 		       rec->dstdir.ino, rec->dstdir.gen,
439f2dd45e5SAndreas Jaekel 		       rec->file.ino, rec->file.gen,
44035d4e8ddSAndreas Jaekel 		       rec->file.mtime, rec->file.ctime,
44135d4e8ddSAndreas Jaekel 		       rec->srcdir.mtime, rec->srcdir.ctime,
44235d4e8ddSAndreas Jaekel 		       rec->dstdir.mtime, rec->dstdir.ctime,
443f2dd45e5SAndreas Jaekel 		       ZEV_SRCNAME(rec),
444f2dd45e5SAndreas Jaekel 		       ZEV_DSTNAME(rec));
445f2dd45e5SAndreas Jaekel 	}
446*16ff6b2fSAndreas Jaekel }
447f2dd45e5SAndreas Jaekel 
448f2dd45e5SAndreas Jaekel static void
449205ed6bfSAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
450205ed6bfSAndreas Jaekel {
451205ed6bfSAndreas Jaekel 	int     i;
452205ed6bfSAndreas Jaekel 
453205ed6bfSAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
454205ed6bfSAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
455205ed6bfSAndreas Jaekel 	}
456205ed6bfSAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
457205ed6bfSAndreas Jaekel }
458205ed6bfSAndreas Jaekel 
459205ed6bfSAndreas Jaekel static void
460f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf)
461f2dd45e5SAndreas Jaekel {
462f2dd45e5SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
463f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
464f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
465205ed6bfSAndreas Jaekel 	zev_sig_t *sig;
466205ed6bfSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
467205ed6bfSAndreas Jaekel 	int i;
468f2dd45e5SAndreas Jaekel 
469205ed6bfSAndreas Jaekel 	if (verbose) {
470*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
471*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
472*16ff6b2fSAndreas Jaekel 		zpf("  offset: %llu", rec->offset);
473*16ff6b2fSAndreas Jaekel 		zpf("  length: %llu", rec->length);
474*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
475*16ff6b2fSAndreas Jaekel 		znl();
476205ed6bfSAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
477205ed6bfSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
478205ed6bfSAndreas Jaekel 			sig += i;
479205ed6bfSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
480205ed6bfSAndreas Jaekel 			printf("  sig: level %d, offset %llu, value %s\n",
481205ed6bfSAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
482205ed6bfSAndreas Jaekel 		}
483*16ff6b2fSAndreas Jaekel 	} else {
484*16ff6b2fSAndreas Jaekel 		printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
485*16ff6b2fSAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
486*16ff6b2fSAndreas Jaekel 		       rec->file.ino, rec->file.gen,
487*16ff6b2fSAndreas Jaekel 		       rec->offset, rec->length);
488205ed6bfSAndreas Jaekel 	}
489f2dd45e5SAndreas Jaekel }
490f2dd45e5SAndreas Jaekel 
491f2dd45e5SAndreas Jaekel static void
492f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf)
493f2dd45e5SAndreas Jaekel {
494f2dd45e5SAndreas Jaekel 	zev_print_znode_write(buf);
495f2dd45e5SAndreas Jaekel }
496f2dd45e5SAndreas Jaekel 
497f2dd45e5SAndreas Jaekel static void
498f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf)
499f2dd45e5SAndreas Jaekel {
500f2dd45e5SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
501f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
502f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
503f2dd45e5SAndreas Jaekel 
504*16ff6b2fSAndreas Jaekel 	if (verbose) {
505*16ff6b2fSAndreas Jaekel 		zpf("%s %s", ct, zev_op_name[rec->op - ZEV_OP_MIN]);
506*16ff6b2fSAndreas Jaekel 		zpf("  guid: %llu", rec->guid);
507*16ff6b2fSAndreas Jaekel 		zev_print_inode_info("file", &rec->file);
508*16ff6b2fSAndreas Jaekel 		znl();
509*16ff6b2fSAndreas Jaekel 	} else {
51035d4e8ddSAndreas Jaekel 		printf("%s %s: file=%llu.%llu mtime=%llu\n",
511f2dd45e5SAndreas Jaekel 		       ct, zev_op_name[rec->op - ZEV_OP_MIN],
51235d4e8ddSAndreas Jaekel 		       rec->file.ino, rec->file.gen, rec->file.mtime);
513f2dd45e5SAndreas Jaekel 	}
514*16ff6b2fSAndreas Jaekel }
515f2dd45e5SAndreas Jaekel 
516f2dd45e5SAndreas Jaekel static void
517f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf)
518f2dd45e5SAndreas Jaekel {
519f2dd45e5SAndreas Jaekel 	zev_print_znode_setattr(buf);
520f2dd45e5SAndreas Jaekel }
521f2dd45e5SAndreas Jaekel 
522f2dd45e5SAndreas Jaekel static void
523aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
524aafc540fSAndreas Jaekel {
525f2dd45e5SAndreas Jaekel 	int record_len;
526f2dd45e5SAndreas Jaekel 	int op;
527aafc540fSAndreas Jaekel 
528f2dd45e5SAndreas Jaekel 	record_len = *(uint32_t *)buf;
529f2dd45e5SAndreas Jaekel 	if (record_len != len) {
530f2dd45e5SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
531f2dd45e5SAndreas Jaekel 		        record_len, len);
532aafc540fSAndreas Jaekel 		exit(1);
533aafc540fSAndreas Jaekel 	}
534f2dd45e5SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
535aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
536f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
537aafc540fSAndreas Jaekel 		exit(1);
538aafc540fSAndreas Jaekel 	}
539f2dd45e5SAndreas Jaekel 	switch (op) {
540f2dd45e5SAndreas Jaekel 	case ZEV_OP_ERROR:
541f2dd45e5SAndreas Jaekel 		zev_print_error(buf);
542aafc540fSAndreas Jaekel 		break;
543888fea18SAndreas Jaekel 	case ZEV_OP_MARK:
544888fea18SAndreas Jaekel 		zev_print_mark(buf);
545888fea18SAndreas Jaekel 		break;
546f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
547f2dd45e5SAndreas Jaekel 		zev_print_zfs_mount(buf);
548aafc540fSAndreas Jaekel 		break;
549f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
550f2dd45e5SAndreas Jaekel 		zev_print_zfs_umount(buf);
551aafc540fSAndreas Jaekel 		break;
552f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
553f2dd45e5SAndreas Jaekel 		zev_print_zvol_truncate(buf);
554aafc540fSAndreas Jaekel 		break;
555f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
556f2dd45e5SAndreas Jaekel 		zev_print_zvol_write(buf);
557f2dd45e5SAndreas Jaekel 		break;
558f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
559f2dd45e5SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
560f2dd45e5SAndreas Jaekel 		break;
561f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
562f2dd45e5SAndreas Jaekel 		zev_print_znode_create(buf);
563f2dd45e5SAndreas Jaekel 		break;
564f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
565f2dd45e5SAndreas Jaekel 		zev_print_znode_mkdir(buf);
566f2dd45e5SAndreas Jaekel 		break;
567f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
568f2dd45e5SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
569f2dd45e5SAndreas Jaekel 		break;
570f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
571f2dd45e5SAndreas Jaekel 		zev_print_znode_remove(buf);
572f2dd45e5SAndreas Jaekel 		break;
573f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
574f2dd45e5SAndreas Jaekel 		zev_print_znode_rmdir(buf);
575f2dd45e5SAndreas Jaekel 		break;
576f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
577f2dd45e5SAndreas Jaekel 		zev_print_znode_link(buf);
578f2dd45e5SAndreas Jaekel 		break;
579f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
580f2dd45e5SAndreas Jaekel 		zev_print_znode_symlink(buf);
581f2dd45e5SAndreas Jaekel 		break;
582f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
583f2dd45e5SAndreas Jaekel 		zev_print_znode_rename(buf);
584f2dd45e5SAndreas Jaekel 		break;
585f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
586f2dd45e5SAndreas Jaekel 		zev_print_znode_write(buf);
587f2dd45e5SAndreas Jaekel 		break;
588f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
589f2dd45e5SAndreas Jaekel 		zev_print_znode_truncate(buf);
590f2dd45e5SAndreas Jaekel 		break;
591f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
592f2dd45e5SAndreas Jaekel 		zev_print_znode_setattr(buf);
593f2dd45e5SAndreas Jaekel 		break;
594f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
595f2dd45e5SAndreas Jaekel 		zev_print_znode_acl(buf);
596aafc540fSAndreas Jaekel 		break;
597aafc540fSAndreas Jaekel 	default:
598f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
599aafc540fSAndreas Jaekel 		exit(1);
600aafc540fSAndreas Jaekel 	}
601aafc540fSAndreas Jaekel }
602aafc540fSAndreas Jaekel 
603add9520fSAndreas Jaekel static int
6046a6a51eeSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
605a18c35b9SAndreas Jaekel {
606a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
607a18c35b9SAndreas Jaekel 	int ret;
608aafc540fSAndreas Jaekel 	char buf[4096];
609d979f56cSAndreas Jaekel 	zev_event_t *ev;
610d979f56cSAndreas Jaekel 	int off = 0;
611add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
612add9520fSAndreas Jaekel 	int q_fd;
613add9520fSAndreas Jaekel 
6146a6a51eeSAndreas Jaekel 	if (create_tmp_queue) {
615add9520fSAndreas Jaekel 		aq.zev_max_queue_len = 0;
616add9520fSAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
617add9520fSAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
618add9520fSAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
619add9520fSAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
620add9520fSAndreas Jaekel 
621add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
622add9520fSAndreas Jaekel 			perror("adding temporary queue failed");
623add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
624add9520fSAndreas Jaekel 		}
625add9520fSAndreas Jaekel 
6266a6a51eeSAndreas Jaekel 		snprintf(buf, sizeof(buf),
6276a6a51eeSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
628add9520fSAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
629add9520fSAndreas Jaekel 		if (q_fd < 0) {
630add9520fSAndreas Jaekel 			perror("opening queue device failed");
631add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
632add9520fSAndreas Jaekel 		}
6336a6a51eeSAndreas Jaekel 	} else {
6346a6a51eeSAndreas Jaekel 		q_fd = fd;
6356a6a51eeSAndreas Jaekel 	}
636add9520fSAndreas Jaekel 
637a18c35b9SAndreas Jaekel 	while (1) {
638add9520fSAndreas Jaekel 		pfd[0].fd = q_fd;
639a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
640a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
641a18c35b9SAndreas Jaekel 		if (ret < 0) {
642a18c35b9SAndreas Jaekel 			perror("poll failed");
6436a6a51eeSAndreas Jaekel 			close(q_fd);
644add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
645a18c35b9SAndreas Jaekel 		}
646a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
647a18c35b9SAndreas Jaekel 			continue;
648a18c35b9SAndreas Jaekel 		/* data available */
649add9520fSAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
650a18c35b9SAndreas Jaekel 		if (ret < 0) {
651a18c35b9SAndreas Jaekel 			perror("read failed");
6526a6a51eeSAndreas Jaekel 			close(q_fd);
653add9520fSAndreas Jaekel 			return(EXIT_FAILURE);
654a18c35b9SAndreas Jaekel 		}
655a18c35b9SAndreas Jaekel 		if (ret == 0)
656a18c35b9SAndreas Jaekel 			continue;
657d979f56cSAndreas Jaekel 		while (ret > off) {
658d979f56cSAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
659d979f56cSAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
660d979f56cSAndreas Jaekel 			off += ev->header.record_len;
661d979f56cSAndreas Jaekel 		}
662149d0affSAndreas Jaekel 		off = 0;
663a18c35b9SAndreas Jaekel 	}
6646a6a51eeSAndreas Jaekel 	if (create_tmp_queue)
665add9520fSAndreas Jaekel 		close(q_fd);
666add9520fSAndreas Jaekel 	return EXIT_SUCCESS;
667a18c35b9SAndreas Jaekel }
668a18c35b9SAndreas Jaekel 
669a18c35b9SAndreas Jaekel static void
670a18c35b9SAndreas Jaekel usage(char *progname)
671a18c35b9SAndreas Jaekel {
672add9520fSAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
673add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
674add9520fSAndreas Jaekel 	fprintf(stderr, " Status information:\n");
675a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
676a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
677add9520fSAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
678add9520fSAndreas Jaekel 	        "information\n");
679add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
680add9520fSAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
681add9520fSAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
682add9520fSAndreas Jaekel 	        "length\n");
683add9520fSAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
684add9520fSAndreas Jaekel 	        "this pool\n");
685a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
686add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
687add9520fSAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
688add9520fSAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
6896a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
6906a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
691add9520fSAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
692add9520fSAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
693add9520fSAndreas Jaekel 	        "(default)\n");
694add9520fSAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
695add9520fSAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
6966a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
697add9520fSAndreas Jaekel 	        "length\n");
698add9520fSAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
699add9520fSAndreas Jaekel 	        "throttle\n");
700add9520fSAndreas Jaekel 	fprintf(stderr, "\n");
701add9520fSAndreas Jaekel 	fprintf(stderr, " Other options:\n");
702add9520fSAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
703add9520fSAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
7046a6a51eeSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
7056a6a51eeSAndreas Jaekel 		"queue name\n");
706888fea18SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
70742110aacSAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
70842110aacSAndreas Jaekel 		"checksums\n");
709*16ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: additional output "
710205ed6bfSAndreas Jaekel 	        "for some operations\n");
711*16ff6b2fSAndreas Jaekel 	fprintf(stderr, "   -g                   grep-friendly event output, "
712*16ff6b2fSAndreas Jaekel 	        "one event per line\n");
713a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
714a18c35b9SAndreas Jaekel }
715a18c35b9SAndreas Jaekel 
716a18c35b9SAndreas Jaekel static int
7176a6a51eeSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
718a18c35b9SAndreas Jaekel {
719add9520fSAndreas Jaekel 	zev_ioctl_add_queue_t aq;
720add9520fSAndreas Jaekel 	int namelen;
721a18c35b9SAndreas Jaekel 
722add9520fSAndreas Jaekel 	namelen = strlen(arg);
723add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
724add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
725a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
726a18c35b9SAndreas Jaekel 	}
727add9520fSAndreas Jaekel 
728add9520fSAndreas Jaekel 	aq.zev_namelen = namelen;
729add9520fSAndreas Jaekel 	strcpy(aq.zev_name, arg);
7306a6a51eeSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;
7316a6a51eeSAndreas Jaekel 	if (blocking) {
7326a6a51eeSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
7336a6a51eeSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
7346a6a51eeSAndreas Jaekel 	} else {
735add9520fSAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
7366a6a51eeSAndreas Jaekel 	}
737add9520fSAndreas Jaekel 
738add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
739add9520fSAndreas Jaekel 		perror("adding queue failed");
740a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
741a18c35b9SAndreas Jaekel 	}
742a18c35b9SAndreas Jaekel 	return (0);
743a18c35b9SAndreas Jaekel }
744a18c35b9SAndreas Jaekel 
745a18c35b9SAndreas Jaekel static int
746add9520fSAndreas Jaekel zev_remove_queue(int fd, char *arg)
747fec460f8SAndreas Jaekel {
748add9520fSAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
749add9520fSAndreas Jaekel 	int namelen;
750fec460f8SAndreas Jaekel 
751add9520fSAndreas Jaekel 	namelen = strlen(arg);
752add9520fSAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
753add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
754fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
755fec460f8SAndreas Jaekel 	}
756add9520fSAndreas Jaekel 
7576a6a51eeSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
7586a6a51eeSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
759add9520fSAndreas Jaekel 
760add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
761add9520fSAndreas Jaekel 		perror("removing queue failed");
762add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
763add9520fSAndreas Jaekel 	}
764add9520fSAndreas Jaekel 	return (0);
765add9520fSAndreas Jaekel }
766add9520fSAndreas Jaekel 
767add9520fSAndreas Jaekel static int
768add9520fSAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
769add9520fSAndreas Jaekel {
770add9520fSAndreas Jaekel 	uint64_t maxqueuelen;
771add9520fSAndreas Jaekel 
772add9520fSAndreas Jaekel 	errno = 0;
773add9520fSAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
774add9520fSAndreas Jaekel 	if (errno) {
775add9520fSAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
776add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
777add9520fSAndreas Jaekel 	}
778add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
779add9520fSAndreas Jaekel 		perror("setting max queue length failed");
780fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
781fec460f8SAndreas Jaekel 	}
782fec460f8SAndreas Jaekel 	return (0);
783fec460f8SAndreas Jaekel }
784fec460f8SAndreas Jaekel 
785fec460f8SAndreas Jaekel static int
786a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
787a18c35b9SAndreas Jaekel {
788a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
789a18c35b9SAndreas Jaekel 	int len;
790a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
791a18c35b9SAndreas Jaekel 	len = strlen(poolname);
792a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
793a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
794a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
795a18c35b9SAndreas Jaekel 	}
796a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
797a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
798a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
799a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
800a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
801a18c35b9SAndreas Jaekel 	}
802a18c35b9SAndreas Jaekel 	return (0);
803a18c35b9SAndreas Jaekel }
804a18c35b9SAndreas Jaekel 
805a18c35b9SAndreas Jaekel int
806a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
807a18c35b9SAndreas Jaekel {
808a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
809a18c35b9SAndreas Jaekel }
810a18c35b9SAndreas Jaekel 
811a18c35b9SAndreas Jaekel int
812a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
813a18c35b9SAndreas Jaekel {
814a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
815a18c35b9SAndreas Jaekel }
816a18c35b9SAndreas Jaekel 
817888fea18SAndreas Jaekel static int
818add9520fSAndreas Jaekel zev_debug_info(int fd)
819add9520fSAndreas Jaekel {
820add9520fSAndreas Jaekel 	zev_ioctl_debug_info_t di;
821add9520fSAndreas Jaekel 
822add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
823add9520fSAndreas Jaekel 		perror("getting zev debug info failed");
824add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
825add9520fSAndreas Jaekel 	}
826add9520fSAndreas Jaekel 
827add9520fSAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
828205ed6bfSAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
829205ed6bfSAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
830205ed6bfSAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
831add9520fSAndreas Jaekel 	return 0;
832add9520fSAndreas Jaekel }
833add9520fSAndreas Jaekel 
834add9520fSAndreas Jaekel static int
835888fea18SAndreas Jaekel zev_mark(int fd, char *arg)
836888fea18SAndreas Jaekel {
837888fea18SAndreas Jaekel 	zev_ioctl_mark_t *mark;
838888fea18SAndreas Jaekel 	uint64_t guid;
839888fea18SAndreas Jaekel 	int len;
840888fea18SAndreas Jaekel 	char *p;
841888fea18SAndreas Jaekel 
842888fea18SAndreas Jaekel 	p = strchr(arg, ':');
843888fea18SAndreas Jaekel 	if (!p) {
844888fea18SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
845888fea18SAndreas Jaekel 		        "e.g. '123:hello'\n");
846888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
847888fea18SAndreas Jaekel 	}
848888fea18SAndreas Jaekel 	*p = '\n';
849888fea18SAndreas Jaekel 	p++;
850888fea18SAndreas Jaekel 
851888fea18SAndreas Jaekel 	errno = 0;
852add9520fSAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
853888fea18SAndreas Jaekel 	if (errno) {
854888fea18SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
855888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
856888fea18SAndreas Jaekel 	}
857888fea18SAndreas Jaekel 
858888fea18SAndreas Jaekel 	len = strlen(p);
859888fea18SAndreas Jaekel 
860888fea18SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
861888fea18SAndreas Jaekel 	if (!mark) {
862888fea18SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
863888fea18SAndreas Jaekel 		        strerror(errno));
864888fea18SAndreas Jaekel 		exit (EXIT_FAILURE);
865888fea18SAndreas Jaekel 	}
866888fea18SAndreas Jaekel 	mark->zev_guid = guid;
867888fea18SAndreas Jaekel 	mark->zev_mark_id = 0;
868888fea18SAndreas Jaekel 	mark->zev_payload_len = len;
869888fea18SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
870888fea18SAndreas Jaekel 
871888fea18SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
872888fea18SAndreas Jaekel 		perror("queueing mark failed");
873888fea18SAndreas Jaekel 		return (EXIT_FAILURE);
874888fea18SAndreas Jaekel 	}
875888fea18SAndreas Jaekel 
876888fea18SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
877888fea18SAndreas Jaekel 	return (0);
878888fea18SAndreas Jaekel }
879888fea18SAndreas Jaekel 
880add9520fSAndreas Jaekel static int
881add9520fSAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
882add9520fSAndreas Jaekel {
883add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
884add9520fSAndreas Jaekel 
8856a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
8866a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
887add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
888add9520fSAndreas Jaekel 		return EXIT_FAILURE;
889add9520fSAndreas Jaekel 	}
8906a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
891add9520fSAndreas Jaekel 
892add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
893add9520fSAndreas Jaekel 		perror("getting queue properties failed");
894add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
895add9520fSAndreas Jaekel 	}
896add9520fSAndreas Jaekel 	if (block) {
897add9520fSAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
898add9520fSAndreas Jaekel 	} else {
899add9520fSAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
900add9520fSAndreas Jaekel 	}
901add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
902add9520fSAndreas Jaekel 		perror("setting queue properties failed");
903add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
904add9520fSAndreas Jaekel 	}
905add9520fSAndreas Jaekel 	return (0);
906add9520fSAndreas Jaekel }
907add9520fSAndreas Jaekel 
908add9520fSAndreas Jaekel static int
909add9520fSAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
910add9520fSAndreas Jaekel {
911add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
912add9520fSAndreas Jaekel 
913add9520fSAndreas Jaekel 	if (!len) {
914add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
915add9520fSAndreas Jaekel 		return EXIT_FAILURE;
916add9520fSAndreas Jaekel 	}
917add9520fSAndreas Jaekel 
9186a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9196a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
920add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
921add9520fSAndreas Jaekel 		return EXIT_FAILURE;
922add9520fSAndreas Jaekel 	}
9236a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
924add9520fSAndreas Jaekel 
925add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
926add9520fSAndreas Jaekel 		perror("getting queue properties failed");
927add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
928add9520fSAndreas Jaekel 	}
929add9520fSAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
930add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
931add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
932add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
933add9520fSAndreas Jaekel 	}
934add9520fSAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
935add9520fSAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
936add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
937add9520fSAndreas Jaekel 	}
938add9520fSAndreas Jaekel 
939add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
940add9520fSAndreas Jaekel 		perror("setting queue properties failed");
941add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
942add9520fSAndreas Jaekel 	}
943add9520fSAndreas Jaekel 	return (0);
944add9520fSAndreas Jaekel }
945add9520fSAndreas Jaekel 
946add9520fSAndreas Jaekel static int
947add9520fSAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
948add9520fSAndreas Jaekel {
949add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
950add9520fSAndreas Jaekel 
951add9520fSAndreas Jaekel 	if (!len) {
952add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
953add9520fSAndreas Jaekel 		return EXIT_FAILURE;
954add9520fSAndreas Jaekel 	}
955add9520fSAndreas Jaekel 
9566a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9576a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
958add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
959add9520fSAndreas Jaekel 		return EXIT_FAILURE;
960add9520fSAndreas Jaekel 	}
9616a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
962add9520fSAndreas Jaekel 
963add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
964add9520fSAndreas Jaekel 		perror("getting queue properties failed");
965add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
966add9520fSAndreas Jaekel 	}
967add9520fSAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
968add9520fSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
969add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
970add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
971add9520fSAndreas Jaekel 	}
9726a6a51eeSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
973add9520fSAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
974add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
975add9520fSAndreas Jaekel 	}
976add9520fSAndreas Jaekel 
977add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
978add9520fSAndreas Jaekel 		perror("setting queue properties failed");
979add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
980add9520fSAndreas Jaekel 	}
981add9520fSAndreas Jaekel 	return (0);
982add9520fSAndreas Jaekel }
983add9520fSAndreas Jaekel 
984add9520fSAndreas Jaekel static int
985add9520fSAndreas Jaekel zev_queue_properties(int fd, char *arg)
986add9520fSAndreas Jaekel {
987add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
988add9520fSAndreas Jaekel 
9896a6a51eeSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
9906a6a51eeSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
991add9520fSAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
992add9520fSAndreas Jaekel 		return EXIT_FAILURE;
993add9520fSAndreas Jaekel 	}
9946a6a51eeSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
995add9520fSAndreas Jaekel 
996add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
997add9520fSAndreas Jaekel 		perror("getting queue properties failed");
998add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
999add9520fSAndreas Jaekel 	}
1000add9520fSAndreas Jaekel 
1001add9520fSAndreas Jaekel 	printf("queue        : %s\n", arg);
1002add9520fSAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
1003add9520fSAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
1004add9520fSAndreas Jaekel 	printf("persistent   : %s\n",
1005add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
1006add9520fSAndreas Jaekel 	printf("blocking     : %s\n",
1007add9520fSAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
1008add9520fSAndreas Jaekel 
1009add9520fSAndreas Jaekel 	return (0);
1010add9520fSAndreas Jaekel }
1011add9520fSAndreas Jaekel 
1012add9520fSAndreas Jaekel static int
1013add9520fSAndreas Jaekel zev_list_queues(int fd)
1014add9520fSAndreas Jaekel {
1015add9520fSAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
1016add9520fSAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
1017add9520fSAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
1018add9520fSAndreas Jaekel 	uint64_t	i;
1019add9520fSAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
1020add9520fSAndreas Jaekel 
1021add9520fSAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
1022add9520fSAndreas Jaekel 		perror("getting queue list failed");
1023add9520fSAndreas Jaekel 		return (EXIT_FAILURE);
1024add9520fSAndreas Jaekel 	}
1025add9520fSAndreas Jaekel 
1026add9520fSAndreas Jaekel 	printf("Name                                     Size       "
1027add9520fSAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
1028add9520fSAndreas Jaekel 
1029add9520fSAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
1030add9520fSAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
1031add9520fSAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
1032add9520fSAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
1033add9520fSAndreas Jaekel 
10346a6a51eeSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
10356a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
10366a6a51eeSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
10376a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1038add9520fSAndreas Jaekel 
1039add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
1040add9520fSAndreas Jaekel 			if (errno == ENOENT)
1041add9520fSAndreas Jaekel 				continue;
1042add9520fSAndreas Jaekel 			perror("getting queue properties failed");
1043add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1044add9520fSAndreas Jaekel 		}
1045add9520fSAndreas Jaekel 
10466a6a51eeSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
10476a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
10486a6a51eeSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
10496a6a51eeSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
1050add9520fSAndreas Jaekel 
1051add9520fSAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
1052add9520fSAndreas Jaekel 			if (errno == ENOENT)
1053add9520fSAndreas Jaekel 				continue;
1054add9520fSAndreas Jaekel 			perror("getting statistics data failed");
1055add9520fSAndreas Jaekel 			return (EXIT_FAILURE);
1056add9520fSAndreas Jaekel 		}
1057add9520fSAndreas Jaekel 
1058add9520fSAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
1059add9520fSAndreas Jaekel 		       " %-3s %-3s\n",
1060add9520fSAndreas Jaekel 			name,
1061add9520fSAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
1062add9520fSAndreas Jaekel 			gqp.zev_max_queue_len,
1063add9520fSAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
1064add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
1065add9520fSAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
1066add9520fSAndreas Jaekel 				 "yes" : "no");
1067add9520fSAndreas Jaekel 	}
1068add9520fSAndreas Jaekel 
1069add9520fSAndreas Jaekel 	return (0);
1070add9520fSAndreas Jaekel }
1071add9520fSAndreas Jaekel 
107242110aacSAndreas Jaekel static int
107342110aacSAndreas Jaekel zev_checksum(int dev_fd, char *filename)
107442110aacSAndreas Jaekel {
107542110aacSAndreas Jaekel 	int fd;
107642110aacSAndreas Jaekel 	offset_t off;
107742110aacSAndreas Jaekel 	offset_t data;
107842110aacSAndreas Jaekel 	zev_sig_t *sig;
107942110aacSAndreas Jaekel 	char *buf;
108042110aacSAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
108142110aacSAndreas Jaekel 	int i;
108242110aacSAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
108342110aacSAndreas Jaekel 	int buf_size;
108442110aacSAndreas Jaekel 
108542110aacSAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
108642110aacSAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
108742110aacSAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
108842110aacSAndreas Jaekel 	if (!buf) {
108942110aacSAndreas Jaekel 		perror("can't allocate checksum buffer");
109042110aacSAndreas Jaekel 		return (EXIT_FAILURE);
109142110aacSAndreas Jaekel 	}
109242110aacSAndreas Jaekel 
109342110aacSAndreas Jaekel 	fd = open(filename, O_RDONLY);
109442110aacSAndreas Jaekel 	if (fd < 0) {
109542110aacSAndreas Jaekel 		perror("can't open file");
109642110aacSAndreas Jaekel 		return (EXIT_FAILURE);
109742110aacSAndreas Jaekel 	}
109842110aacSAndreas Jaekel 
109942110aacSAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
110042110aacSAndreas Jaekel 	gs->zev_fd = fd;
110142110aacSAndreas Jaekel 	gs->zev_bufsize = buf_size;
110242110aacSAndreas Jaekel 
110342110aacSAndreas Jaekel 	off = 0;
110442110aacSAndreas Jaekel 	data = 0;
110542110aacSAndreas Jaekel 	while (1) {
110642110aacSAndreas Jaekel 		errno = 0;
110742110aacSAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
110842110aacSAndreas Jaekel 		if (data < 0) {
110942110aacSAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
111042110aacSAndreas Jaekel 				break;
111142110aacSAndreas Jaekel 			perror("llseek failed");
111242110aacSAndreas Jaekel 			goto err;
111342110aacSAndreas Jaekel 		}
111442110aacSAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
111542110aacSAndreas Jaekel 		off = data + ZEV_L1_SIZE;
111642110aacSAndreas Jaekel 
111742110aacSAndreas Jaekel 		gs->zev_offset = data;
111842110aacSAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
111942110aacSAndreas Jaekel 
112042110aacSAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
112142110aacSAndreas Jaekel 			perror("ioctl to get signatures failed");
112242110aacSAndreas Jaekel 			goto err;
112342110aacSAndreas Jaekel 		}
112442110aacSAndreas Jaekel 
112542110aacSAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
112642110aacSAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
112742110aacSAndreas Jaekel 			sig += i;
112842110aacSAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
112942110aacSAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
113042110aacSAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
113142110aacSAndreas Jaekel 		}
113242110aacSAndreas Jaekel 	}
113342110aacSAndreas Jaekel 
113442110aacSAndreas Jaekel 	free(buf);
113542110aacSAndreas Jaekel 	close(fd);
113642110aacSAndreas Jaekel 	return 0;
113742110aacSAndreas Jaekel err:
113842110aacSAndreas Jaekel 	free(buf);
113942110aacSAndreas Jaekel 	close(fd);
114042110aacSAndreas Jaekel 	return (EXIT_FAILURE);
114142110aacSAndreas Jaekel }
114242110aacSAndreas Jaekel 
1143a18c35b9SAndreas Jaekel int
1144a18c35b9SAndreas Jaekel main(int argc, char **argv)
1145a18c35b9SAndreas Jaekel {
1146a18c35b9SAndreas Jaekel 	int fd;
1147a18c35b9SAndreas Jaekel 	int c;
1148a18c35b9SAndreas Jaekel 	extern char *optarg;
11496a6a51eeSAndreas Jaekel 	int create_tmp_queue = 1;
11506a6a51eeSAndreas Jaekel 	char buf[MAXPATHLEN];
1151a18c35b9SAndreas Jaekel 
1152a18c35b9SAndreas Jaekel 	/* open device */
1153a18c35b9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
1154a18c35b9SAndreas Jaekel 	if (fd < 0) {
1155a18c35b9SAndreas Jaekel 		perror("opening zev device failed");
1156a18c35b9SAndreas Jaekel 		return EXIT_FAILURE;
1157a18c35b9SAndreas Jaekel 	}
11586a6a51eeSAndreas Jaekel 	while ((c = getopt(argc, argv,
1159*16ff6b2fSAndreas Jaekel 	                   "gvspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){
1160a18c35b9SAndreas Jaekel 		switch(c) {
1161*16ff6b2fSAndreas Jaekel 		case 'g':
1162*16ff6b2fSAndreas Jaekel 			grep_friendly++;
1163*16ff6b2fSAndreas Jaekel 			verbose++;
1164*16ff6b2fSAndreas Jaekel 			break;
1165205ed6bfSAndreas Jaekel 		case 'v':
1166205ed6bfSAndreas Jaekel 			verbose++;
1167205ed6bfSAndreas Jaekel 			break;
1168a18c35b9SAndreas Jaekel 		case 's':
1169add9520fSAndreas Jaekel 			return zev_statistics(fd);
1170a18c35b9SAndreas Jaekel 		case 'p':
11716a6a51eeSAndreas Jaekel 			return zev_poll_events(fd, create_tmp_queue);
117242110aacSAndreas Jaekel 		case 'c':
117342110aacSAndreas Jaekel 			return zev_checksum(fd, optarg);
1174add9520fSAndreas Jaekel 		case 'D':
1175add9520fSAndreas Jaekel 			return zev_debug_info(fd);
1176a18c35b9SAndreas Jaekel 		case 'd':
1177add9520fSAndreas Jaekel 			close(fd);
1178a18c35b9SAndreas Jaekel 			zev_device = optarg;
1179add9520fSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
1180add9520fSAndreas Jaekel 			if (fd < 0) {
1181add9520fSAndreas Jaekel 				perror("opening zev device failed");
1182add9520fSAndreas Jaekel 				return EXIT_FAILURE;
1183add9520fSAndreas Jaekel 			}
11846a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
11856a6a51eeSAndreas Jaekel 			break;
11866a6a51eeSAndreas Jaekel 		case 'q':
11876a6a51eeSAndreas Jaekel 			snprintf(buf, sizeof(buf),
11886a6a51eeSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
11896a6a51eeSAndreas Jaekel 			close(fd);
11906a6a51eeSAndreas Jaekel 			zev_device = buf;
11916a6a51eeSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
11926a6a51eeSAndreas Jaekel 			if (fd < 0) {
11936a6a51eeSAndreas Jaekel 				perror("opening zev device failed");
11946a6a51eeSAndreas Jaekel 				return EXIT_FAILURE;
11956a6a51eeSAndreas Jaekel 			}
11966a6a51eeSAndreas Jaekel 			create_tmp_queue = 0;
1197a18c35b9SAndreas Jaekel 			break;
1198add9520fSAndreas Jaekel 		case 'l':
1199add9520fSAndreas Jaekel 			return zev_list_queues(fd);
1200add9520fSAndreas Jaekel 		case 'Q':
1201add9520fSAndreas Jaekel 			return zev_set_global_max_queue_len(fd, optarg);
12026a6a51eeSAndreas Jaekel 		case 'L':
1203add9520fSAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg, argv[optind]);
1204fec460f8SAndreas Jaekel 		case 't':
1205add9520fSAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg,
1206add9520fSAndreas Jaekel 			                                     argv[optind]);
1207a18c35b9SAndreas Jaekel 		case 'm':
1208a18c35b9SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
1209a18c35b9SAndreas Jaekel 		case 'M':
1210a18c35b9SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
1211888fea18SAndreas Jaekel 		case 'k':
1212888fea18SAndreas Jaekel 			return zev_mark(fd, optarg);
1213add9520fSAndreas Jaekel 		case 'a':
12146a6a51eeSAndreas Jaekel 			return zev_add_queue(fd, optarg, 0);
12156a6a51eeSAndreas Jaekel 		case 'A':
12166a6a51eeSAndreas Jaekel 			return zev_add_queue(fd, optarg, 1);
1217add9520fSAndreas Jaekel 		case 'r':
1218add9520fSAndreas Jaekel 			return zev_remove_queue(fd, optarg);
1219add9520fSAndreas Jaekel 		case 'b':
1220add9520fSAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 0);
1221add9520fSAndreas Jaekel 		case 'B':
1222add9520fSAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 1);
1223add9520fSAndreas Jaekel 		case 'P':
1224add9520fSAndreas Jaekel 			return zev_queue_properties(fd, optarg);
1225a18c35b9SAndreas Jaekel 		case 'h':
1226a18c35b9SAndreas Jaekel 		case '?':
1227a18c35b9SAndreas Jaekel 		default:
1228a18c35b9SAndreas Jaekel 			usage(argv[0]);
1229a18c35b9SAndreas Jaekel 		}
1230a18c35b9SAndreas Jaekel 	}
1231a18c35b9SAndreas Jaekel 	usage(argv[0]);
1232a18c35b9SAndreas Jaekel 	close(fd);
1233add9520fSAndreas Jaekel 	return EXIT_FAILURE;
1234a18c35b9SAndreas Jaekel }
1235a18c35b9SAndreas Jaekel 
1236