xref: /titanic_51/usr/src/cmd/zevadm/zevadm.c (revision 63aba447d4f59953bcd260ebf5a898c8511c28ed)
12bb8e5e2SAndreas Jaekel #include <stdio.h>
22bb8e5e2SAndreas Jaekel #include <unistd.h>
32bb8e5e2SAndreas Jaekel #include <stdlib.h>
42bb8e5e2SAndreas Jaekel #include <fcntl.h>
52bb8e5e2SAndreas Jaekel #include <stropts.h>
62bb8e5e2SAndreas Jaekel #include <poll.h>
72bb8e5e2SAndreas Jaekel #include <string.h>
82bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h>
92bb8e5e2SAndreas Jaekel #include <errno.h>
102bb8e5e2SAndreas Jaekel 
112bb8e5e2SAndreas Jaekel #define OP_STATISTICS		(1 << 0)
122bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS		(1 << 1)
132bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL		(1 << 2)
142bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL		(1 << 3)
152bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN	(1 << 4)
162bb8e5e2SAndreas Jaekel 
172bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev"
182bb8e5e2SAndreas Jaekel 
192bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
202bb8e5e2SAndreas Jaekel 
219193e9c2SAndreas Jaekel static char *zev_op_name[] = {
229193e9c2SAndreas Jaekel 	"ZEV_OP_ERROR",
239193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
249193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
259193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
269193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
279193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
289193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
299193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
309193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
319193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
329193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
339193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
349193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
359193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
369193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
379193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
389193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
399193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
409193e9c2SAndreas Jaekel 	NULL
419193e9c2SAndreas Jaekel };
429193e9c2SAndreas Jaekel 
432bb8e5e2SAndreas Jaekel static void
442bb8e5e2SAndreas Jaekel zev_statistics(int fd)
452bb8e5e2SAndreas Jaekel {
462bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
472bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
482bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
492bb8e5e2SAndreas Jaekel 		exit (EXIT_FAILURE);
502bb8e5e2SAndreas Jaekel 	}
512bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
522bb8e5e2SAndreas Jaekel 
532bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
542bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
55205a9bc9SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
56205a9bc9SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
572bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
582bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
592bb8e5e2SAndreas Jaekel 
602bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
612bb8e5e2SAndreas Jaekel 
622bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
632bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
642bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
652bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
662bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
672bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
682bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
692bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
702bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
712bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
722bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
732bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
742bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
752bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
762bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
772bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
782bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
792bb8e5e2SAndreas Jaekel }
802bb8e5e2SAndreas Jaekel 
812bb8e5e2SAndreas Jaekel static void
82*63aba447SAndreas Jaekel zev_print_error(char *buf)
83*63aba447SAndreas Jaekel {
84*63aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
85*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
86*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
87*63aba447SAndreas Jaekel 
88*63aba447SAndreas Jaekel 	printf("%s %s: failed_op=%s msg=%s\n",
89*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
90*63aba447SAndreas Jaekel 	       zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec));
91*63aba447SAndreas Jaekel }
92*63aba447SAndreas Jaekel 
93*63aba447SAndreas Jaekel static void
94*63aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
95*63aba447SAndreas Jaekel {
96*63aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
97*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
98*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
99*63aba447SAndreas Jaekel 
100*63aba447SAndreas Jaekel 	printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n",
101*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
102*63aba447SAndreas Jaekel 	       rec->guid,
103*63aba447SAndreas Jaekel 	       rec->remount ? "true" : "false",
104*63aba447SAndreas Jaekel 	       ZEV_DATASET(rec),
105*63aba447SAndreas Jaekel 	       ZEV_MOUNTPOINT(rec));
106*63aba447SAndreas Jaekel }
107*63aba447SAndreas Jaekel 
108*63aba447SAndreas Jaekel static void
109*63aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
110*63aba447SAndreas Jaekel {
111*63aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
112*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
113*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
114*63aba447SAndreas Jaekel 
115*63aba447SAndreas Jaekel 	printf("%s %s: guid=%llu\n",
116*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
117*63aba447SAndreas Jaekel 	       rec->guid);
118*63aba447SAndreas Jaekel }
119*63aba447SAndreas Jaekel 
120*63aba447SAndreas Jaekel static void
121*63aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
122*63aba447SAndreas Jaekel {
123*63aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
124*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
125*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
126*63aba447SAndreas Jaekel 
127*63aba447SAndreas Jaekel 	printf("%s %s: guid=%llu offset=%llu length=%llu\n",
128*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
129*63aba447SAndreas Jaekel 	       rec->guid,
130*63aba447SAndreas Jaekel 	       rec->offset,
131*63aba447SAndreas Jaekel 	       rec->length);
132*63aba447SAndreas Jaekel }
133*63aba447SAndreas Jaekel 
134*63aba447SAndreas Jaekel static void
135*63aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
136*63aba447SAndreas Jaekel {
137*63aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
138*63aba447SAndreas Jaekel }
139*63aba447SAndreas Jaekel 
140*63aba447SAndreas Jaekel static void
141*63aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
142*63aba447SAndreas Jaekel {
143*63aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
144*63aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
145*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
146*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
147*63aba447SAndreas Jaekel 
148*63aba447SAndreas Jaekel 	printf("%s %s: guid=%llu file=%llu.%llu\n",
149*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
150*63aba447SAndreas Jaekel 	       rec->guid,
151*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
152*63aba447SAndreas Jaekel }
153*63aba447SAndreas Jaekel 
154*63aba447SAndreas Jaekel static void
155*63aba447SAndreas Jaekel zev_print_znode_create(char *buf)
156*63aba447SAndreas Jaekel {
157*63aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
158*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
159*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
160*63aba447SAndreas Jaekel 
161*63aba447SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu name='%s'\n",
162*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
163*63aba447SAndreas Jaekel 	       rec->guid,
164*63aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
165*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
166*63aba447SAndreas Jaekel 	       ZEV_NAME(rec));
167*63aba447SAndreas Jaekel }
168*63aba447SAndreas Jaekel 
169*63aba447SAndreas Jaekel static void
170*63aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
171*63aba447SAndreas Jaekel {
172*63aba447SAndreas Jaekel 	zev_print_znode_create(buf);
173*63aba447SAndreas Jaekel }
174*63aba447SAndreas Jaekel 
175*63aba447SAndreas Jaekel static void
176*63aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
177*63aba447SAndreas Jaekel {
178*63aba447SAndreas Jaekel 	zev_print_znode_create(buf);
179*63aba447SAndreas Jaekel }
180*63aba447SAndreas Jaekel 
181*63aba447SAndreas Jaekel static void
182*63aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
183*63aba447SAndreas Jaekel {
184*63aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
185*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
186*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
187*63aba447SAndreas Jaekel 
188*63aba447SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu name='%s'\n",
189*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
190*63aba447SAndreas Jaekel 	       rec->guid,
191*63aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
192*63aba447SAndreas Jaekel 	       ZEV_NAME(rec));
193*63aba447SAndreas Jaekel }
194*63aba447SAndreas Jaekel 
195*63aba447SAndreas Jaekel static void
196*63aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
197*63aba447SAndreas Jaekel {
198*63aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
199*63aba447SAndreas Jaekel }
200*63aba447SAndreas Jaekel 
201*63aba447SAndreas Jaekel static void
202*63aba447SAndreas Jaekel zev_print_znode_link(char *buf)
203*63aba447SAndreas Jaekel {
204*63aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
205*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
206*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
207*63aba447SAndreas Jaekel 
208*63aba447SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s'\n",
209*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
210*63aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
211*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
212*63aba447SAndreas Jaekel 	       ZEV_NAME(rec));
213*63aba447SAndreas Jaekel 	printf("links: %d\n", rec->file.links);
214*63aba447SAndreas Jaekel }
215*63aba447SAndreas Jaekel 
216*63aba447SAndreas Jaekel static void
217*63aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
218*63aba447SAndreas Jaekel {
219*63aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
220*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
221*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
222*63aba447SAndreas Jaekel 
223*63aba447SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n",
224*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
225*63aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
226*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
227*63aba447SAndreas Jaekel 	       ZEV_NAME(rec),
228*63aba447SAndreas Jaekel 	       ZEV_LINK(rec));
229*63aba447SAndreas Jaekel }
230*63aba447SAndreas Jaekel 
231*63aba447SAndreas Jaekel static void
232*63aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
233*63aba447SAndreas Jaekel {
234*63aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
235*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
236*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
237*63aba447SAndreas Jaekel 
238*63aba447SAndreas Jaekel 	printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu "
239*63aba447SAndreas Jaekel 	       "srcname='%s' dstname='%s'\n",
240*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
241*63aba447SAndreas Jaekel 	       rec->srcdir.ino, rec->srcdir.gen,
242*63aba447SAndreas Jaekel 	       rec->dstdir.ino, rec->dstdir.gen,
243*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
244*63aba447SAndreas Jaekel 	       ZEV_SRCNAME(rec),
245*63aba447SAndreas Jaekel 	       ZEV_DSTNAME(rec));
246*63aba447SAndreas Jaekel }
247*63aba447SAndreas Jaekel 
248*63aba447SAndreas Jaekel static void
249*63aba447SAndreas Jaekel zev_print_znode_write(char *buf)
250*63aba447SAndreas Jaekel {
251*63aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
252*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
253*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
254*63aba447SAndreas Jaekel 
255*63aba447SAndreas Jaekel 	printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
256*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
257*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
258*63aba447SAndreas Jaekel 	       rec->offset, rec->length);
259*63aba447SAndreas Jaekel }
260*63aba447SAndreas Jaekel 
261*63aba447SAndreas Jaekel static void
262*63aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
263*63aba447SAndreas Jaekel {
264*63aba447SAndreas Jaekel 	zev_print_znode_write(buf);
265*63aba447SAndreas Jaekel }
266*63aba447SAndreas Jaekel 
267*63aba447SAndreas Jaekel static void
268*63aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
269*63aba447SAndreas Jaekel {
270*63aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
271*63aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
272*63aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
273*63aba447SAndreas Jaekel 
274*63aba447SAndreas Jaekel 	printf("%s %s: file=%llu.%llu\n",
275*63aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
276*63aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
277*63aba447SAndreas Jaekel }
278*63aba447SAndreas Jaekel 
279*63aba447SAndreas Jaekel static void
280*63aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
281*63aba447SAndreas Jaekel {
282*63aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
283*63aba447SAndreas Jaekel }
284*63aba447SAndreas Jaekel 
285*63aba447SAndreas Jaekel static void
2869193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
2879193e9c2SAndreas Jaekel {
288*63aba447SAndreas Jaekel 	int record_len;
289*63aba447SAndreas Jaekel 	int op;
2909193e9c2SAndreas Jaekel 
291*63aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
292*63aba447SAndreas Jaekel 	if (record_len != len) {
293*63aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
294*63aba447SAndreas Jaekel 		        record_len, len);
2959193e9c2SAndreas Jaekel 		exit(1);
2969193e9c2SAndreas Jaekel 	}
297*63aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
2989193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
299*63aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
3009193e9c2SAndreas Jaekel 		exit(1);
3019193e9c2SAndreas Jaekel 	}
302*63aba447SAndreas Jaekel 	switch (op) {
303*63aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
304*63aba447SAndreas Jaekel 		zev_print_error(buf);
3059193e9c2SAndreas Jaekel 		break;
306*63aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
307*63aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
3089193e9c2SAndreas Jaekel 		break;
309*63aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
310*63aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
3119193e9c2SAndreas Jaekel 		break;
312*63aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
313*63aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
3149193e9c2SAndreas Jaekel 		break;
315*63aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
316*63aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
317*63aba447SAndreas Jaekel 		break;
318*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
319*63aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
320*63aba447SAndreas Jaekel 		break;
321*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
322*63aba447SAndreas Jaekel 		zev_print_znode_create(buf);
323*63aba447SAndreas Jaekel 		break;
324*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
325*63aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
326*63aba447SAndreas Jaekel 		break;
327*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
328*63aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
329*63aba447SAndreas Jaekel 		break;
330*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
331*63aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
332*63aba447SAndreas Jaekel 		break;
333*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
334*63aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
335*63aba447SAndreas Jaekel 		break;
336*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
337*63aba447SAndreas Jaekel 		zev_print_znode_link(buf);
338*63aba447SAndreas Jaekel 		break;
339*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
340*63aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
341*63aba447SAndreas Jaekel 		break;
342*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
343*63aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
344*63aba447SAndreas Jaekel 		break;
345*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
346*63aba447SAndreas Jaekel 		zev_print_znode_write(buf);
347*63aba447SAndreas Jaekel 		break;
348*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
349*63aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
350*63aba447SAndreas Jaekel 		break;
351*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
352*63aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
353*63aba447SAndreas Jaekel 		break;
354*63aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
355*63aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
3569193e9c2SAndreas Jaekel 		break;
3579193e9c2SAndreas Jaekel 	default:
358*63aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
3599193e9c2SAndreas Jaekel 		exit(1);
3609193e9c2SAndreas Jaekel 	}
3619193e9c2SAndreas Jaekel }
3629193e9c2SAndreas Jaekel 
3639193e9c2SAndreas Jaekel static void
3642bb8e5e2SAndreas Jaekel zev_poll_events(int fd)
3652bb8e5e2SAndreas Jaekel {
3662bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
3672bb8e5e2SAndreas Jaekel 	int ret;
3689193e9c2SAndreas Jaekel 	char buf[4096];
3692bb8e5e2SAndreas Jaekel 	while (1) {
3702bb8e5e2SAndreas Jaekel 		pfd[0].fd = fd;
3712bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
3722bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
3732bb8e5e2SAndreas Jaekel 		if (ret < 0) {
3742bb8e5e2SAndreas Jaekel 			perror("poll failed");
3752bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
3762bb8e5e2SAndreas Jaekel 		}
3772bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
3782bb8e5e2SAndreas Jaekel 			continue;
3792bb8e5e2SAndreas Jaekel 		/* data available */
3802bb8e5e2SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
3812bb8e5e2SAndreas Jaekel 		if (ret < 0) {
3822bb8e5e2SAndreas Jaekel 			perror("read failed");
3832bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
3842bb8e5e2SAndreas Jaekel 		}
3852bb8e5e2SAndreas Jaekel 		if (ret == 0)
3862bb8e5e2SAndreas Jaekel 			continue;
3879193e9c2SAndreas Jaekel 		zev_print_event(buf, ret);
3882bb8e5e2SAndreas Jaekel 	}
3892bb8e5e2SAndreas Jaekel 	return;
3902bb8e5e2SAndreas Jaekel }
3912bb8e5e2SAndreas Jaekel 
3922bb8e5e2SAndreas Jaekel static void
3932bb8e5e2SAndreas Jaekel usage(char *progname)
3942bb8e5e2SAndreas Jaekel {
3952bb8e5e2SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
3962bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
3972bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
3982bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
399205a9bc9SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
4002bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
4012bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
4022bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
4032bb8e5e2SAndreas Jaekel 	    ZEV_DEVICE);
4042bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
4052bb8e5e2SAndreas Jaekel }
4062bb8e5e2SAndreas Jaekel 
4072bb8e5e2SAndreas Jaekel static int
4082bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
4092bb8e5e2SAndreas Jaekel {
4102bb8e5e2SAndreas Jaekel 	uint64_t maxqueuelen;
4112bb8e5e2SAndreas Jaekel 
4122bb8e5e2SAndreas Jaekel 	errno = 0;
4132bb8e5e2SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
4142bb8e5e2SAndreas Jaekel 	if (errno) {
4152bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
4162bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4172bb8e5e2SAndreas Jaekel 	}
4182bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
4192bb8e5e2SAndreas Jaekel 		perror("setting max queue length failed");
4202bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4212bb8e5e2SAndreas Jaekel 	}
4222bb8e5e2SAndreas Jaekel 	return (0);
4232bb8e5e2SAndreas Jaekel }
4242bb8e5e2SAndreas Jaekel 
4252bb8e5e2SAndreas Jaekel static int
426205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
427205a9bc9SAndreas Jaekel {
428205a9bc9SAndreas Jaekel 	uint64_t queuelen;
429205a9bc9SAndreas Jaekel 
430205a9bc9SAndreas Jaekel 	errno = 0;
431205a9bc9SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
432205a9bc9SAndreas Jaekel 	if (errno) {
433205a9bc9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
434205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
435205a9bc9SAndreas Jaekel 	}
436205a9bc9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
437205a9bc9SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
438205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
439205a9bc9SAndreas Jaekel 	}
440205a9bc9SAndreas Jaekel 	return (0);
441205a9bc9SAndreas Jaekel }
442205a9bc9SAndreas Jaekel 
443205a9bc9SAndreas Jaekel static int
4442bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
4452bb8e5e2SAndreas Jaekel {
4462bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
4472bb8e5e2SAndreas Jaekel 	int len;
4482bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
4492bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
4502bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
4512bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
4522bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4532bb8e5e2SAndreas Jaekel 	}
4542bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
4552bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
4562bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
4572bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
4582bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4592bb8e5e2SAndreas Jaekel 	}
4602bb8e5e2SAndreas Jaekel 	return (0);
4612bb8e5e2SAndreas Jaekel }
4622bb8e5e2SAndreas Jaekel 
4632bb8e5e2SAndreas Jaekel int
4642bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
4652bb8e5e2SAndreas Jaekel {
4662bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
4672bb8e5e2SAndreas Jaekel }
4682bb8e5e2SAndreas Jaekel 
4692bb8e5e2SAndreas Jaekel int
4702bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
4712bb8e5e2SAndreas Jaekel {
4722bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
4732bb8e5e2SAndreas Jaekel }
4742bb8e5e2SAndreas Jaekel 
4752bb8e5e2SAndreas Jaekel int
4762bb8e5e2SAndreas Jaekel main(int argc, char **argv)
4772bb8e5e2SAndreas Jaekel {
4782bb8e5e2SAndreas Jaekel 	int fd;
4792bb8e5e2SAndreas Jaekel 	int c;
4802bb8e5e2SAndreas Jaekel 	int ops = 0;
4812bb8e5e2SAndreas Jaekel 	extern char *optarg;
4822bb8e5e2SAndreas Jaekel 
4832bb8e5e2SAndreas Jaekel 	/* open device */
4842bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
4852bb8e5e2SAndreas Jaekel 	if (fd < 0) {
4862bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
4872bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
4882bb8e5e2SAndreas Jaekel 	}
489205a9bc9SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) {
4902bb8e5e2SAndreas Jaekel 		switch(c) {
4912bb8e5e2SAndreas Jaekel 		case 's':
4922bb8e5e2SAndreas Jaekel 			ops |= OP_STATISTICS;
4932bb8e5e2SAndreas Jaekel 			break;
4942bb8e5e2SAndreas Jaekel 		case 'p':
4952bb8e5e2SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
4962bb8e5e2SAndreas Jaekel 			break;
4972bb8e5e2SAndreas Jaekel 		case 'd':
4982bb8e5e2SAndreas Jaekel 			zev_device = optarg;
4992bb8e5e2SAndreas Jaekel 			break;
5002bb8e5e2SAndreas Jaekel 		case 'q':
5012bb8e5e2SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
502205a9bc9SAndreas Jaekel 		case 't':
503205a9bc9SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
5042bb8e5e2SAndreas Jaekel 		case 'm':
5052bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
5062bb8e5e2SAndreas Jaekel 		case 'M':
5072bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
5082bb8e5e2SAndreas Jaekel 		case 'h':
5092bb8e5e2SAndreas Jaekel 		case '?':
5102bb8e5e2SAndreas Jaekel 		default:
5112bb8e5e2SAndreas Jaekel 			usage(argv[0]);
5122bb8e5e2SAndreas Jaekel 		}
5132bb8e5e2SAndreas Jaekel 	}
5142bb8e5e2SAndreas Jaekel 	if (!ops)
5152bb8e5e2SAndreas Jaekel 		usage(argv[0]);
5162bb8e5e2SAndreas Jaekel 	if (ops & OP_STATISTICS)
5172bb8e5e2SAndreas Jaekel 		zev_statistics(fd);
5182bb8e5e2SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
5192bb8e5e2SAndreas Jaekel 		zev_poll_events(fd);
5202bb8e5e2SAndreas Jaekel 	close(fd);
5212bb8e5e2SAndreas Jaekel 	return EXIT_SUCCESS;
5222bb8e5e2SAndreas Jaekel }
5232bb8e5e2SAndreas Jaekel 
524