xref: /titanic_51/usr/src/cmd/zevadm/zevadm.c (revision 6db5d4ec7067f6ac90788b6d5f24002d82d0f21e)
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",
2301c2c787SAndreas Jaekel 	"ZEV_OP_MARK",
249193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
259193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
269193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
279193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
289193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
299193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
309193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
319193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
329193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
339193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
349193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
359193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
369193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
379193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
389193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
399193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
409193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
419193e9c2SAndreas Jaekel 	NULL
429193e9c2SAndreas Jaekel };
439193e9c2SAndreas Jaekel 
442bb8e5e2SAndreas Jaekel static void
452bb8e5e2SAndreas Jaekel zev_statistics(int fd)
462bb8e5e2SAndreas Jaekel {
472bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
482bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
492bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
502bb8e5e2SAndreas Jaekel 		exit (EXIT_FAILURE);
512bb8e5e2SAndreas Jaekel 	}
522bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
532bb8e5e2SAndreas Jaekel 
542bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
552bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
56205a9bc9SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
57205a9bc9SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
582bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
592bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
602bb8e5e2SAndreas Jaekel 
612bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
622bb8e5e2SAndreas Jaekel 
632bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
642bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
652bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
662bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
672bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
682bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
692bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
702bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
712bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
722bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
732bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
742bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
752bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
762bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
772bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
782bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
792bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
802bb8e5e2SAndreas Jaekel }
812bb8e5e2SAndreas Jaekel 
822bb8e5e2SAndreas Jaekel static void
8363aba447SAndreas Jaekel zev_print_error(char *buf)
8463aba447SAndreas Jaekel {
8563aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
8663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
8763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
8863aba447SAndreas Jaekel 
8963aba447SAndreas Jaekel 	printf("%s %s: failed_op=%s msg=%s\n",
9063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
9163aba447SAndreas Jaekel 	       zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec));
9263aba447SAndreas Jaekel }
9363aba447SAndreas Jaekel 
9463aba447SAndreas Jaekel static void
9501c2c787SAndreas Jaekel zev_print_mark(char *buf)
9601c2c787SAndreas Jaekel {
9701c2c787SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
9801c2c787SAndreas Jaekel 	time_t op_time = rec->op_time;
9901c2c787SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
10001c2c787SAndreas Jaekel 
10101c2c787SAndreas Jaekel 	printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
10201c2c787SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id,
10301c2c787SAndreas Jaekel 	       rec->payload_len);
10401c2c787SAndreas Jaekel }
10501c2c787SAndreas Jaekel 
10601c2c787SAndreas Jaekel static void
10763aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
10863aba447SAndreas Jaekel {
10963aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
11063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
11163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
11263aba447SAndreas Jaekel 
11363aba447SAndreas Jaekel 	printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n",
11463aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
11563aba447SAndreas Jaekel 	       rec->guid,
11663aba447SAndreas Jaekel 	       rec->remount ? "true" : "false",
11763aba447SAndreas Jaekel 	       ZEV_DATASET(rec),
11863aba447SAndreas Jaekel 	       ZEV_MOUNTPOINT(rec));
11963aba447SAndreas Jaekel }
12063aba447SAndreas Jaekel 
12163aba447SAndreas Jaekel static void
12263aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
12363aba447SAndreas Jaekel {
12463aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
12563aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
12663aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
12763aba447SAndreas Jaekel 
12863aba447SAndreas Jaekel 	printf("%s %s: guid=%llu\n",
12963aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
13063aba447SAndreas Jaekel 	       rec->guid);
13163aba447SAndreas Jaekel }
13263aba447SAndreas Jaekel 
13363aba447SAndreas Jaekel static void
13463aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
13563aba447SAndreas Jaekel {
13663aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
13763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
13863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
13963aba447SAndreas Jaekel 
14063aba447SAndreas Jaekel 	printf("%s %s: guid=%llu offset=%llu length=%llu\n",
14163aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
14263aba447SAndreas Jaekel 	       rec->guid,
14363aba447SAndreas Jaekel 	       rec->offset,
14463aba447SAndreas Jaekel 	       rec->length);
14563aba447SAndreas Jaekel }
14663aba447SAndreas Jaekel 
14763aba447SAndreas Jaekel static void
14863aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
14963aba447SAndreas Jaekel {
15063aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
15163aba447SAndreas Jaekel }
15263aba447SAndreas Jaekel 
15363aba447SAndreas Jaekel static void
15463aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
15563aba447SAndreas Jaekel {
15663aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
15763aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
15863aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
15963aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
16063aba447SAndreas Jaekel 
16163aba447SAndreas Jaekel 	printf("%s %s: guid=%llu file=%llu.%llu\n",
16263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
16363aba447SAndreas Jaekel 	       rec->guid,
16463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
16563aba447SAndreas Jaekel }
16663aba447SAndreas Jaekel 
16763aba447SAndreas Jaekel static void
16863aba447SAndreas Jaekel zev_print_znode_create(char *buf)
16963aba447SAndreas Jaekel {
17063aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
17163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
17263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
17363aba447SAndreas Jaekel 
174c035b1e8SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
175c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
17663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
17763aba447SAndreas Jaekel 	       rec->guid,
17863aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
17963aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
180c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->parent.mtime,
18163aba447SAndreas Jaekel 	       ZEV_NAME(rec));
18263aba447SAndreas Jaekel }
18363aba447SAndreas Jaekel 
18463aba447SAndreas Jaekel static void
18563aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
18663aba447SAndreas Jaekel {
18763aba447SAndreas Jaekel 	zev_print_znode_create(buf);
18863aba447SAndreas Jaekel }
18963aba447SAndreas Jaekel 
19063aba447SAndreas Jaekel static void
19163aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
19263aba447SAndreas Jaekel {
19363aba447SAndreas Jaekel 	zev_print_znode_create(buf);
19463aba447SAndreas Jaekel }
19563aba447SAndreas Jaekel 
19663aba447SAndreas Jaekel static void
19763aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
19863aba447SAndreas Jaekel {
19963aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
20063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
20163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
20263aba447SAndreas Jaekel 
203*6db5d4ecSAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n",
20463aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
20563aba447SAndreas Jaekel 	       rec->guid,
20663aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
207*6db5d4ecSAndreas Jaekel 	       rec->file.mtime,
20863aba447SAndreas Jaekel 	       ZEV_NAME(rec));
20963aba447SAndreas Jaekel }
21063aba447SAndreas Jaekel 
21163aba447SAndreas Jaekel static void
21263aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
21363aba447SAndreas Jaekel {
21463aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
21563aba447SAndreas Jaekel }
21663aba447SAndreas Jaekel 
21763aba447SAndreas Jaekel static void
21863aba447SAndreas Jaekel zev_print_znode_link(char *buf)
21963aba447SAndreas Jaekel {
22063aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
22163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
22263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
22363aba447SAndreas Jaekel 
22403101f54SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu "
22503101f54SAndreas Jaekel 	       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
22663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
22763aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
22863aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
22903101f54SAndreas Jaekel 	       rec->file.ctime, rec->parent.ctime,
23063aba447SAndreas Jaekel 	       ZEV_NAME(rec));
23163aba447SAndreas Jaekel 	printf("links: %d\n", rec->file.links);
23263aba447SAndreas Jaekel }
23363aba447SAndreas Jaekel 
23463aba447SAndreas Jaekel static void
23563aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
23663aba447SAndreas Jaekel {
23763aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
23863aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
23963aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
24063aba447SAndreas Jaekel 
24163aba447SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n",
24263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
24363aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
24463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
24563aba447SAndreas Jaekel 	       ZEV_NAME(rec),
24663aba447SAndreas Jaekel 	       ZEV_LINK(rec));
24763aba447SAndreas Jaekel }
24863aba447SAndreas Jaekel 
24963aba447SAndreas Jaekel static void
25063aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
25163aba447SAndreas Jaekel {
25263aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
25363aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
25463aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
25563aba447SAndreas Jaekel 
25663aba447SAndreas Jaekel 	printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu "
257c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, "
258c035b1e8SAndreas Jaekel 	       "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, "
25963aba447SAndreas Jaekel 	       "srcname='%s' dstname='%s'\n",
26063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
26163aba447SAndreas Jaekel 	       rec->srcdir.ino, rec->srcdir.gen,
26263aba447SAndreas Jaekel 	       rec->dstdir.ino, rec->dstdir.gen,
26363aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
264c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->file.ctime,
265c035b1e8SAndreas Jaekel 	       rec->srcdir.mtime, rec->srcdir.ctime,
266c035b1e8SAndreas Jaekel 	       rec->dstdir.mtime, rec->dstdir.ctime,
26763aba447SAndreas Jaekel 	       ZEV_SRCNAME(rec),
26863aba447SAndreas Jaekel 	       ZEV_DSTNAME(rec));
26963aba447SAndreas Jaekel }
27063aba447SAndreas Jaekel 
27163aba447SAndreas Jaekel static void
27263aba447SAndreas Jaekel zev_print_znode_write(char *buf)
27363aba447SAndreas Jaekel {
27463aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
27563aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
27663aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
27763aba447SAndreas Jaekel 
27863aba447SAndreas Jaekel 	printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
27963aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
28063aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
28163aba447SAndreas Jaekel 	       rec->offset, rec->length);
28263aba447SAndreas Jaekel }
28363aba447SAndreas Jaekel 
28463aba447SAndreas Jaekel static void
28563aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
28663aba447SAndreas Jaekel {
28763aba447SAndreas Jaekel 	zev_print_znode_write(buf);
28863aba447SAndreas Jaekel }
28963aba447SAndreas Jaekel 
29063aba447SAndreas Jaekel static void
29163aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
29263aba447SAndreas Jaekel {
29363aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
29463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
29563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
29663aba447SAndreas Jaekel 
297c035b1e8SAndreas Jaekel 	printf("%s %s: file=%llu.%llu mtime=%llu\n",
29863aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
299c035b1e8SAndreas Jaekel 	       rec->file.ino, rec->file.gen, rec->file.mtime);
30063aba447SAndreas Jaekel }
30163aba447SAndreas Jaekel 
30263aba447SAndreas Jaekel static void
30363aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
30463aba447SAndreas Jaekel {
30563aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
30663aba447SAndreas Jaekel }
30763aba447SAndreas Jaekel 
30863aba447SAndreas Jaekel static void
3099193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
3109193e9c2SAndreas Jaekel {
31163aba447SAndreas Jaekel 	int record_len;
31263aba447SAndreas Jaekel 	int op;
3139193e9c2SAndreas Jaekel 
31463aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
31563aba447SAndreas Jaekel 	if (record_len != len) {
31663aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
31763aba447SAndreas Jaekel 		        record_len, len);
3189193e9c2SAndreas Jaekel 		exit(1);
3199193e9c2SAndreas Jaekel 	}
32063aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
3219193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
32263aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
3239193e9c2SAndreas Jaekel 		exit(1);
3249193e9c2SAndreas Jaekel 	}
32563aba447SAndreas Jaekel 	switch (op) {
32663aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
32763aba447SAndreas Jaekel 		zev_print_error(buf);
3289193e9c2SAndreas Jaekel 		break;
32901c2c787SAndreas Jaekel 	case ZEV_OP_MARK:
33001c2c787SAndreas Jaekel 		zev_print_mark(buf);
33101c2c787SAndreas Jaekel 		break;
33263aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
33363aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
3349193e9c2SAndreas Jaekel 		break;
33563aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
33663aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
3379193e9c2SAndreas Jaekel 		break;
33863aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
33963aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
3409193e9c2SAndreas Jaekel 		break;
34163aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
34263aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
34363aba447SAndreas Jaekel 		break;
34463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
34563aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
34663aba447SAndreas Jaekel 		break;
34763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
34863aba447SAndreas Jaekel 		zev_print_znode_create(buf);
34963aba447SAndreas Jaekel 		break;
35063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
35163aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
35263aba447SAndreas Jaekel 		break;
35363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
35463aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
35563aba447SAndreas Jaekel 		break;
35663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
35763aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
35863aba447SAndreas Jaekel 		break;
35963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
36063aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
36163aba447SAndreas Jaekel 		break;
36263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
36363aba447SAndreas Jaekel 		zev_print_znode_link(buf);
36463aba447SAndreas Jaekel 		break;
36563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
36663aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
36763aba447SAndreas Jaekel 		break;
36863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
36963aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
37063aba447SAndreas Jaekel 		break;
37163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
37263aba447SAndreas Jaekel 		zev_print_znode_write(buf);
37363aba447SAndreas Jaekel 		break;
37463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
37563aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
37663aba447SAndreas Jaekel 		break;
37763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
37863aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
37963aba447SAndreas Jaekel 		break;
38063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
38163aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
3829193e9c2SAndreas Jaekel 		break;
3839193e9c2SAndreas Jaekel 	default:
38463aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
3859193e9c2SAndreas Jaekel 		exit(1);
3869193e9c2SAndreas Jaekel 	}
3879193e9c2SAndreas Jaekel }
3889193e9c2SAndreas Jaekel 
3899193e9c2SAndreas Jaekel static void
3902bb8e5e2SAndreas Jaekel zev_poll_events(int fd)
3912bb8e5e2SAndreas Jaekel {
3922bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
3932bb8e5e2SAndreas Jaekel 	int ret;
3949193e9c2SAndreas Jaekel 	char buf[4096];
39568a46c64SAndreas Jaekel 	zev_event_t	*ev;
39668a46c64SAndreas Jaekel 	int off = 0;
3972bb8e5e2SAndreas Jaekel 	while (1) {
3982bb8e5e2SAndreas Jaekel 		pfd[0].fd = fd;
3992bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
4002bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
4012bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4022bb8e5e2SAndreas Jaekel 			perror("poll failed");
4032bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
4042bb8e5e2SAndreas Jaekel 		}
4052bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
4062bb8e5e2SAndreas Jaekel 			continue;
4072bb8e5e2SAndreas Jaekel 		/* data available */
4082bb8e5e2SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
4092bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4102bb8e5e2SAndreas Jaekel 			perror("read failed");
4112bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
4122bb8e5e2SAndreas Jaekel 		}
4132bb8e5e2SAndreas Jaekel 		if (ret == 0)
4142bb8e5e2SAndreas Jaekel 			continue;
41568a46c64SAndreas Jaekel 		while (ret > off) {
41668a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
41768a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
41868a46c64SAndreas Jaekel 			off += ev->header.record_len;
41968a46c64SAndreas Jaekel 		}
420108668daSAndreas Jaekel 		off = 0;
4212bb8e5e2SAndreas Jaekel 	}
4222bb8e5e2SAndreas Jaekel 	return;
4232bb8e5e2SAndreas Jaekel }
4242bb8e5e2SAndreas Jaekel 
4252bb8e5e2SAndreas Jaekel static void
4262bb8e5e2SAndreas Jaekel usage(char *progname)
4272bb8e5e2SAndreas Jaekel {
4282bb8e5e2SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
4292bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
4302bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
4312bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
432205a9bc9SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
4332bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
4342bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
4352bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
4362bb8e5e2SAndreas Jaekel 	    ZEV_DEVICE);
43701c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>   queue mark event\n");
4382bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
4392bb8e5e2SAndreas Jaekel }
4402bb8e5e2SAndreas Jaekel 
4412bb8e5e2SAndreas Jaekel static int
4422bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
4432bb8e5e2SAndreas Jaekel {
4442bb8e5e2SAndreas Jaekel 	uint64_t maxqueuelen;
4452bb8e5e2SAndreas Jaekel 
4462bb8e5e2SAndreas Jaekel 	errno = 0;
4472bb8e5e2SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
4482bb8e5e2SAndreas Jaekel 	if (errno) {
4492bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
4502bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4512bb8e5e2SAndreas Jaekel 	}
4522bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
4532bb8e5e2SAndreas Jaekel 		perror("setting max queue length failed");
4542bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4552bb8e5e2SAndreas Jaekel 	}
4562bb8e5e2SAndreas Jaekel 	return (0);
4572bb8e5e2SAndreas Jaekel }
4582bb8e5e2SAndreas Jaekel 
4592bb8e5e2SAndreas Jaekel static int
460205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
461205a9bc9SAndreas Jaekel {
462205a9bc9SAndreas Jaekel 	uint64_t queuelen;
463205a9bc9SAndreas Jaekel 
464205a9bc9SAndreas Jaekel 	errno = 0;
465205a9bc9SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
466205a9bc9SAndreas Jaekel 	if (errno) {
467205a9bc9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
468205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
469205a9bc9SAndreas Jaekel 	}
470205a9bc9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
471205a9bc9SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
472205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
473205a9bc9SAndreas Jaekel 	}
474205a9bc9SAndreas Jaekel 	return (0);
475205a9bc9SAndreas Jaekel }
476205a9bc9SAndreas Jaekel 
477205a9bc9SAndreas Jaekel static int
4782bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
4792bb8e5e2SAndreas Jaekel {
4802bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
4812bb8e5e2SAndreas Jaekel 	int len;
4822bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
4832bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
4842bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
4852bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
4862bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4872bb8e5e2SAndreas Jaekel 	}
4882bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
4892bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
4902bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
4912bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
4922bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
4932bb8e5e2SAndreas Jaekel 	}
4942bb8e5e2SAndreas Jaekel 	return (0);
4952bb8e5e2SAndreas Jaekel }
4962bb8e5e2SAndreas Jaekel 
4972bb8e5e2SAndreas Jaekel int
4982bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
4992bb8e5e2SAndreas Jaekel {
5002bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
5012bb8e5e2SAndreas Jaekel }
5022bb8e5e2SAndreas Jaekel 
5032bb8e5e2SAndreas Jaekel int
5042bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
5052bb8e5e2SAndreas Jaekel {
5062bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
5072bb8e5e2SAndreas Jaekel }
5082bb8e5e2SAndreas Jaekel 
50901c2c787SAndreas Jaekel static int
51001c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
51101c2c787SAndreas Jaekel {
51201c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
51301c2c787SAndreas Jaekel 	uint64_t guid;
51401c2c787SAndreas Jaekel 	int len;
51501c2c787SAndreas Jaekel 	char *p;
51601c2c787SAndreas Jaekel 
51701c2c787SAndreas Jaekel 	p = strchr(arg, ':');
51801c2c787SAndreas Jaekel 	if (!p) {
51901c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
52001c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
52101c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
52201c2c787SAndreas Jaekel 	}
52301c2c787SAndreas Jaekel 	*p = '\n';
52401c2c787SAndreas Jaekel 	p++;
52501c2c787SAndreas Jaekel 
52601c2c787SAndreas Jaekel 	errno = 0;
52701c2c787SAndreas Jaekel 	guid = strtoll(optarg, (char **)NULL, 10);
52801c2c787SAndreas Jaekel 	if (errno) {
52901c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
53001c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
53101c2c787SAndreas Jaekel 	}
53201c2c787SAndreas Jaekel 
53301c2c787SAndreas Jaekel 	len = strlen(p);
53401c2c787SAndreas Jaekel 
53501c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
53601c2c787SAndreas Jaekel 	if (!mark) {
53701c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
53801c2c787SAndreas Jaekel 		        strerror(errno));
53901c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
54001c2c787SAndreas Jaekel 	}
54101c2c787SAndreas Jaekel 	mark->zev_guid = guid;
54201c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
54301c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
54401c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
54501c2c787SAndreas Jaekel 
54601c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
54701c2c787SAndreas Jaekel 		perror("queueing mark failed");
54801c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
54901c2c787SAndreas Jaekel 	}
55001c2c787SAndreas Jaekel 
55101c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
55201c2c787SAndreas Jaekel 	return (0);
55301c2c787SAndreas Jaekel }
55401c2c787SAndreas Jaekel 
5552bb8e5e2SAndreas Jaekel int
5562bb8e5e2SAndreas Jaekel main(int argc, char **argv)
5572bb8e5e2SAndreas Jaekel {
5582bb8e5e2SAndreas Jaekel 	int fd;
5592bb8e5e2SAndreas Jaekel 	int c;
5602bb8e5e2SAndreas Jaekel 	int ops = 0;
5612bb8e5e2SAndreas Jaekel 	extern char *optarg;
5622bb8e5e2SAndreas Jaekel 
5632bb8e5e2SAndreas Jaekel 	/* open device */
5642bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
5652bb8e5e2SAndreas Jaekel 	if (fd < 0) {
5662bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
5672bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
5682bb8e5e2SAndreas Jaekel 	}
56901c2c787SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdk:q:t:m:M:h?")) != -1) {
5702bb8e5e2SAndreas Jaekel 		switch(c) {
5712bb8e5e2SAndreas Jaekel 		case 's':
5722bb8e5e2SAndreas Jaekel 			ops |= OP_STATISTICS;
5732bb8e5e2SAndreas Jaekel 			break;
5742bb8e5e2SAndreas Jaekel 		case 'p':
5752bb8e5e2SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
5762bb8e5e2SAndreas Jaekel 			break;
5772bb8e5e2SAndreas Jaekel 		case 'd':
5782bb8e5e2SAndreas Jaekel 			zev_device = optarg;
5792bb8e5e2SAndreas Jaekel 			break;
5802bb8e5e2SAndreas Jaekel 		case 'q':
5812bb8e5e2SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
582205a9bc9SAndreas Jaekel 		case 't':
583205a9bc9SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
5842bb8e5e2SAndreas Jaekel 		case 'm':
5852bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
5862bb8e5e2SAndreas Jaekel 		case 'M':
5872bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
58801c2c787SAndreas Jaekel 		case 'k':
58901c2c787SAndreas Jaekel 			return zev_mark(fd, optarg);
5902bb8e5e2SAndreas Jaekel 		case 'h':
5912bb8e5e2SAndreas Jaekel 		case '?':
5922bb8e5e2SAndreas Jaekel 		default:
5932bb8e5e2SAndreas Jaekel 			usage(argv[0]);
5942bb8e5e2SAndreas Jaekel 		}
5952bb8e5e2SAndreas Jaekel 	}
5962bb8e5e2SAndreas Jaekel 	if (!ops)
5972bb8e5e2SAndreas Jaekel 		usage(argv[0]);
5982bb8e5e2SAndreas Jaekel 	if (ops & OP_STATISTICS)
5992bb8e5e2SAndreas Jaekel 		zev_statistics(fd);
6002bb8e5e2SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
6012bb8e5e2SAndreas Jaekel 		zev_poll_events(fd);
6022bb8e5e2SAndreas Jaekel 	close(fd);
6032bb8e5e2SAndreas Jaekel 	return EXIT_SUCCESS;
6042bb8e5e2SAndreas Jaekel }
6052bb8e5e2SAndreas Jaekel 
606