xref: /titanic_53/usr/src/cmd/zevadm/zevadm.c (revision 4ca7dd5e57ed577c37683b365d3ae8c6e6d4b8d5)
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)
16e9a5e479SAndreas Jaekel #define OP_DEBUG_INFO		(1 << 5)
172bb8e5e2SAndreas Jaekel 
18e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
192bb8e5e2SAndreas Jaekel 
202bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
212bb8e5e2SAndreas Jaekel 
229193e9c2SAndreas Jaekel static char *zev_op_name[] = {
239193e9c2SAndreas Jaekel 	"ZEV_OP_ERROR",
2401c2c787SAndreas Jaekel 	"ZEV_OP_MARK",
259193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
269193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
279193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
289193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
299193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
309193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
319193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
329193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
339193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
349193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
359193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
369193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
379193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
389193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
399193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
409193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
419193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
429193e9c2SAndreas Jaekel 	NULL
439193e9c2SAndreas Jaekel };
449193e9c2SAndreas Jaekel 
45e9a5e479SAndreas Jaekel static int
462bb8e5e2SAndreas Jaekel zev_statistics(int fd)
472bb8e5e2SAndreas Jaekel {
482bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
49e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
502bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
51e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
522bb8e5e2SAndreas Jaekel 	}
532bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
542bb8e5e2SAndreas Jaekel 
552bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
562bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_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 
60e9a5e479SAndreas Jaekel 	printf("    discarded events        : %lu\n",
61e9a5e479SAndreas Jaekel 	    zs.zev_cnt_discarded_events);
62e9a5e479SAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
63e9a5e479SAndreas Jaekel 
642bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
652bb8e5e2SAndreas Jaekel 
662bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
672bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
682bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
692bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
702bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
712bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
722bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
732bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
742bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
752bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
762bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
772bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
782bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
792bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
802bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
812bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
822bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
83e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
842bb8e5e2SAndreas Jaekel }
852bb8e5e2SAndreas Jaekel 
862bb8e5e2SAndreas Jaekel static void
8763aba447SAndreas Jaekel zev_print_error(char *buf)
8863aba447SAndreas Jaekel {
8963aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
9063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
9163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
9263aba447SAndreas Jaekel 
9363aba447SAndreas Jaekel 	printf("%s %s: failed_op=%s msg=%s\n",
9463aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
9563aba447SAndreas Jaekel 	       zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec));
9663aba447SAndreas Jaekel }
9763aba447SAndreas Jaekel 
9863aba447SAndreas Jaekel static void
9901c2c787SAndreas Jaekel zev_print_mark(char *buf)
10001c2c787SAndreas Jaekel {
10101c2c787SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
10201c2c787SAndreas Jaekel 	time_t op_time = rec->op_time;
10301c2c787SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
10401c2c787SAndreas Jaekel 
10501c2c787SAndreas Jaekel 	printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
10601c2c787SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id,
10701c2c787SAndreas Jaekel 	       rec->payload_len);
10801c2c787SAndreas Jaekel }
10901c2c787SAndreas Jaekel 
11001c2c787SAndreas Jaekel static void
11163aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
11263aba447SAndreas Jaekel {
11363aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
11463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
11563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
11663aba447SAndreas Jaekel 
11763aba447SAndreas Jaekel 	printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n",
11863aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
11963aba447SAndreas Jaekel 	       rec->guid,
12063aba447SAndreas Jaekel 	       rec->remount ? "true" : "false",
12163aba447SAndreas Jaekel 	       ZEV_DATASET(rec),
12263aba447SAndreas Jaekel 	       ZEV_MOUNTPOINT(rec));
12363aba447SAndreas Jaekel }
12463aba447SAndreas Jaekel 
12563aba447SAndreas Jaekel static void
12663aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
12763aba447SAndreas Jaekel {
12863aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
12963aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
13063aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
13163aba447SAndreas Jaekel 
13263aba447SAndreas Jaekel 	printf("%s %s: guid=%llu\n",
13363aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
13463aba447SAndreas Jaekel 	       rec->guid);
13563aba447SAndreas Jaekel }
13663aba447SAndreas Jaekel 
13763aba447SAndreas Jaekel static void
13863aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
13963aba447SAndreas Jaekel {
14063aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
14163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
14263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
14363aba447SAndreas Jaekel 
14463aba447SAndreas Jaekel 	printf("%s %s: guid=%llu offset=%llu length=%llu\n",
14563aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
14663aba447SAndreas Jaekel 	       rec->guid,
14763aba447SAndreas Jaekel 	       rec->offset,
14863aba447SAndreas Jaekel 	       rec->length);
14963aba447SAndreas Jaekel }
15063aba447SAndreas Jaekel 
15163aba447SAndreas Jaekel static void
15263aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
15363aba447SAndreas Jaekel {
15463aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
15563aba447SAndreas Jaekel }
15663aba447SAndreas Jaekel 
15763aba447SAndreas Jaekel static void
15863aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
15963aba447SAndreas Jaekel {
16063aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
16163aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
16263aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
16363aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
16463aba447SAndreas Jaekel 
16563aba447SAndreas Jaekel 	printf("%s %s: guid=%llu file=%llu.%llu\n",
16663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
16763aba447SAndreas Jaekel 	       rec->guid,
16863aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
16963aba447SAndreas Jaekel }
17063aba447SAndreas Jaekel 
17163aba447SAndreas Jaekel static void
17263aba447SAndreas Jaekel zev_print_znode_create(char *buf)
17363aba447SAndreas Jaekel {
17463aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
17563aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
17663aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
17763aba447SAndreas Jaekel 
178c035b1e8SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
179c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
18063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
18163aba447SAndreas Jaekel 	       rec->guid,
18263aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
18363aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
184c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->parent.mtime,
18563aba447SAndreas Jaekel 	       ZEV_NAME(rec));
18663aba447SAndreas Jaekel }
18763aba447SAndreas Jaekel 
18863aba447SAndreas Jaekel static void
18963aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
19063aba447SAndreas Jaekel {
19163aba447SAndreas Jaekel 	zev_print_znode_create(buf);
19263aba447SAndreas Jaekel }
19363aba447SAndreas Jaekel 
19463aba447SAndreas Jaekel static void
19563aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
19663aba447SAndreas Jaekel {
19763aba447SAndreas Jaekel 	zev_print_znode_create(buf);
19863aba447SAndreas Jaekel }
19963aba447SAndreas Jaekel 
20063aba447SAndreas Jaekel static void
20163aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
20263aba447SAndreas Jaekel {
20363aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
20463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
20563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
20663aba447SAndreas Jaekel 
2076db5d4ecSAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n",
20863aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
20963aba447SAndreas Jaekel 	       rec->guid,
21063aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
2116db5d4ecSAndreas Jaekel 	       rec->file.mtime,
21263aba447SAndreas Jaekel 	       ZEV_NAME(rec));
21363aba447SAndreas Jaekel }
21463aba447SAndreas Jaekel 
21563aba447SAndreas Jaekel static void
21663aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
21763aba447SAndreas Jaekel {
21863aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
21963aba447SAndreas Jaekel }
22063aba447SAndreas Jaekel 
22163aba447SAndreas Jaekel static void
22263aba447SAndreas Jaekel zev_print_znode_link(char *buf)
22363aba447SAndreas Jaekel {
22463aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
22563aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
22663aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
22763aba447SAndreas Jaekel 
22803101f54SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu "
22903101f54SAndreas Jaekel 	       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
23063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
23163aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
23263aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
23303101f54SAndreas Jaekel 	       rec->file.ctime, rec->parent.ctime,
23463aba447SAndreas Jaekel 	       ZEV_NAME(rec));
23563aba447SAndreas Jaekel 	printf("links: %d\n", rec->file.links);
23663aba447SAndreas Jaekel }
23763aba447SAndreas Jaekel 
23863aba447SAndreas Jaekel static void
23963aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
24063aba447SAndreas Jaekel {
24163aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
24263aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
24363aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
24463aba447SAndreas Jaekel 
24563aba447SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n",
24663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
24763aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
24863aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
24963aba447SAndreas Jaekel 	       ZEV_NAME(rec),
25063aba447SAndreas Jaekel 	       ZEV_LINK(rec));
25163aba447SAndreas Jaekel }
25263aba447SAndreas Jaekel 
25363aba447SAndreas Jaekel static void
25463aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
25563aba447SAndreas Jaekel {
25663aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
25763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
25863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
25963aba447SAndreas Jaekel 
26063aba447SAndreas Jaekel 	printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu "
261c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, "
262c035b1e8SAndreas Jaekel 	       "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, "
26363aba447SAndreas Jaekel 	       "srcname='%s' dstname='%s'\n",
26463aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
26563aba447SAndreas Jaekel 	       rec->srcdir.ino, rec->srcdir.gen,
26663aba447SAndreas Jaekel 	       rec->dstdir.ino, rec->dstdir.gen,
26763aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
268c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->file.ctime,
269c035b1e8SAndreas Jaekel 	       rec->srcdir.mtime, rec->srcdir.ctime,
270c035b1e8SAndreas Jaekel 	       rec->dstdir.mtime, rec->dstdir.ctime,
27163aba447SAndreas Jaekel 	       ZEV_SRCNAME(rec),
27263aba447SAndreas Jaekel 	       ZEV_DSTNAME(rec));
27363aba447SAndreas Jaekel }
27463aba447SAndreas Jaekel 
27563aba447SAndreas Jaekel static void
27663aba447SAndreas Jaekel zev_print_znode_write(char *buf)
27763aba447SAndreas Jaekel {
27863aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
27963aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
28063aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
28163aba447SAndreas Jaekel 
28263aba447SAndreas Jaekel 	printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
28363aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
28463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
28563aba447SAndreas Jaekel 	       rec->offset, rec->length);
28663aba447SAndreas Jaekel }
28763aba447SAndreas Jaekel 
28863aba447SAndreas Jaekel static void
28963aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
29063aba447SAndreas Jaekel {
29163aba447SAndreas Jaekel 	zev_print_znode_write(buf);
29263aba447SAndreas Jaekel }
29363aba447SAndreas Jaekel 
29463aba447SAndreas Jaekel static void
29563aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
29663aba447SAndreas Jaekel {
29763aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
29863aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
29963aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
30063aba447SAndreas Jaekel 
301c035b1e8SAndreas Jaekel 	printf("%s %s: file=%llu.%llu mtime=%llu\n",
30263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
303c035b1e8SAndreas Jaekel 	       rec->file.ino, rec->file.gen, rec->file.mtime);
30463aba447SAndreas Jaekel }
30563aba447SAndreas Jaekel 
30663aba447SAndreas Jaekel static void
30763aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
30863aba447SAndreas Jaekel {
30963aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
31063aba447SAndreas Jaekel }
31163aba447SAndreas Jaekel 
31263aba447SAndreas Jaekel static void
3139193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
3149193e9c2SAndreas Jaekel {
31563aba447SAndreas Jaekel 	int record_len;
31663aba447SAndreas Jaekel 	int op;
3179193e9c2SAndreas Jaekel 
31863aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
31963aba447SAndreas Jaekel 	if (record_len != len) {
32063aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
32163aba447SAndreas Jaekel 		        record_len, len);
3229193e9c2SAndreas Jaekel 		exit(1);
3239193e9c2SAndreas Jaekel 	}
32463aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
3259193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
32663aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
3279193e9c2SAndreas Jaekel 		exit(1);
3289193e9c2SAndreas Jaekel 	}
32963aba447SAndreas Jaekel 	switch (op) {
33063aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
33163aba447SAndreas Jaekel 		zev_print_error(buf);
3329193e9c2SAndreas Jaekel 		break;
33301c2c787SAndreas Jaekel 	case ZEV_OP_MARK:
33401c2c787SAndreas Jaekel 		zev_print_mark(buf);
33501c2c787SAndreas Jaekel 		break;
33663aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
33763aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
3389193e9c2SAndreas Jaekel 		break;
33963aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
34063aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
3419193e9c2SAndreas Jaekel 		break;
34263aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
34363aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
3449193e9c2SAndreas Jaekel 		break;
34563aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
34663aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
34763aba447SAndreas Jaekel 		break;
34863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
34963aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
35063aba447SAndreas Jaekel 		break;
35163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
35263aba447SAndreas Jaekel 		zev_print_znode_create(buf);
35363aba447SAndreas Jaekel 		break;
35463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
35563aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
35663aba447SAndreas Jaekel 		break;
35763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
35863aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
35963aba447SAndreas Jaekel 		break;
36063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
36163aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
36263aba447SAndreas Jaekel 		break;
36363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
36463aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
36563aba447SAndreas Jaekel 		break;
36663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
36763aba447SAndreas Jaekel 		zev_print_znode_link(buf);
36863aba447SAndreas Jaekel 		break;
36963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
37063aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
37163aba447SAndreas Jaekel 		break;
37263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
37363aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
37463aba447SAndreas Jaekel 		break;
37563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
37663aba447SAndreas Jaekel 		zev_print_znode_write(buf);
37763aba447SAndreas Jaekel 		break;
37863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
37963aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
38063aba447SAndreas Jaekel 		break;
38163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
38263aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
38363aba447SAndreas Jaekel 		break;
38463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
38563aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
3869193e9c2SAndreas Jaekel 		break;
3879193e9c2SAndreas Jaekel 	default:
38863aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
3899193e9c2SAndreas Jaekel 		exit(1);
3909193e9c2SAndreas Jaekel 	}
3919193e9c2SAndreas Jaekel }
3929193e9c2SAndreas Jaekel 
393e9a5e479SAndreas Jaekel static int
394*4ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
3952bb8e5e2SAndreas Jaekel {
3962bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
3972bb8e5e2SAndreas Jaekel 	int ret;
3989193e9c2SAndreas Jaekel 	char buf[4096];
39968a46c64SAndreas Jaekel 	zev_event_t *ev;
40068a46c64SAndreas Jaekel 	int off = 0;
401e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
402e9a5e479SAndreas Jaekel 	int q_fd;
403e9a5e479SAndreas Jaekel 
404*4ca7dd5eSAndreas Jaekel 	if (create_tmp_queue) {
405e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = 0;
406e9a5e479SAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
407e9a5e479SAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
408e9a5e479SAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
409e9a5e479SAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
410e9a5e479SAndreas Jaekel 
411e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
412e9a5e479SAndreas Jaekel 			perror("adding temporary queue failed");
413e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
414e9a5e479SAndreas Jaekel 		}
415e9a5e479SAndreas Jaekel 
416*4ca7dd5eSAndreas Jaekel 		snprintf(buf, sizeof(buf),
417*4ca7dd5eSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
418e9a5e479SAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
419e9a5e479SAndreas Jaekel 		if (q_fd < 0) {
420e9a5e479SAndreas Jaekel 			perror("opening queue device failed");
421e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
422e9a5e479SAndreas Jaekel 		}
423*4ca7dd5eSAndreas Jaekel 	} else {
424*4ca7dd5eSAndreas Jaekel 		q_fd = fd;
425*4ca7dd5eSAndreas Jaekel 	}
426e9a5e479SAndreas Jaekel 
4272bb8e5e2SAndreas Jaekel 	while (1) {
428e9a5e479SAndreas Jaekel 		pfd[0].fd = q_fd;
4292bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
4302bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
4312bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4322bb8e5e2SAndreas Jaekel 			perror("poll failed");
433*4ca7dd5eSAndreas Jaekel 			close(q_fd);
434e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4352bb8e5e2SAndreas Jaekel 		}
4362bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
4372bb8e5e2SAndreas Jaekel 			continue;
4382bb8e5e2SAndreas Jaekel 		/* data available */
439e9a5e479SAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
4402bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4412bb8e5e2SAndreas Jaekel 			perror("read failed");
442*4ca7dd5eSAndreas Jaekel 			close(q_fd);
443e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4442bb8e5e2SAndreas Jaekel 		}
4452bb8e5e2SAndreas Jaekel 		if (ret == 0)
4462bb8e5e2SAndreas Jaekel 			continue;
44768a46c64SAndreas Jaekel 		while (ret > off) {
44868a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
44968a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
45068a46c64SAndreas Jaekel 			off += ev->header.record_len;
45168a46c64SAndreas Jaekel 		}
452108668daSAndreas Jaekel 		off = 0;
4532bb8e5e2SAndreas Jaekel 	}
454*4ca7dd5eSAndreas Jaekel 	if (create_tmp_queue)
455e9a5e479SAndreas Jaekel 		close(q_fd);
456e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
4572bb8e5e2SAndreas Jaekel }
4582bb8e5e2SAndreas Jaekel 
4592bb8e5e2SAndreas Jaekel static void
4602bb8e5e2SAndreas Jaekel usage(char *progname)
4612bb8e5e2SAndreas Jaekel {
462e9a5e479SAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
463e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
464e9a5e479SAndreas Jaekel 	fprintf(stderr, " Status information:\n");
4652bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
4662bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
467e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
468e9a5e479SAndreas Jaekel 	        "information\n");
469e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
470e9a5e479SAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
471e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
472e9a5e479SAndreas Jaekel 	        "length\n");
473e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
474e9a5e479SAndreas Jaekel 	        "this pool\n");
4752bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
476e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
477e9a5e479SAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
478e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
479*4ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
480*4ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
481e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
482e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
483e9a5e479SAndreas Jaekel 	        "(default)\n");
484e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
485e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
486*4ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
487e9a5e479SAndreas Jaekel 	        "length\n");
488e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
489e9a5e479SAndreas Jaekel 	        "throttle\n");
490e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
491e9a5e479SAndreas Jaekel 	fprintf(stderr, " Other options:\n");
492e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
493e9a5e479SAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
494*4ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
495*4ca7dd5eSAndreas Jaekel 		"queue name\n");
49601c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
4972bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
4982bb8e5e2SAndreas Jaekel }
4992bb8e5e2SAndreas Jaekel 
5002bb8e5e2SAndreas Jaekel static int
501*4ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
5022bb8e5e2SAndreas Jaekel {
503e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
504e9a5e479SAndreas Jaekel 	int namelen;
5052bb8e5e2SAndreas Jaekel 
506e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
507e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
508e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
5092bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5102bb8e5e2SAndreas Jaekel 	}
511e9a5e479SAndreas Jaekel 
512e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
513e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
514*4ca7dd5eSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;
515*4ca7dd5eSAndreas Jaekel 	if (blocking) {
516*4ca7dd5eSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
517*4ca7dd5eSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
518*4ca7dd5eSAndreas Jaekel 	} else {
519e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
520*4ca7dd5eSAndreas Jaekel 	}
521e9a5e479SAndreas Jaekel 
522e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
523e9a5e479SAndreas Jaekel 		perror("adding queue failed");
5242bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5252bb8e5e2SAndreas Jaekel 	}
5262bb8e5e2SAndreas Jaekel 	return (0);
5272bb8e5e2SAndreas Jaekel }
5282bb8e5e2SAndreas Jaekel 
5292bb8e5e2SAndreas Jaekel static int
530e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg)
531205a9bc9SAndreas Jaekel {
532e9a5e479SAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
533e9a5e479SAndreas Jaekel 	int namelen;
534205a9bc9SAndreas Jaekel 
535e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
536e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
537e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
538205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
539205a9bc9SAndreas Jaekel 	}
540e9a5e479SAndreas Jaekel 
541*4ca7dd5eSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
542*4ca7dd5eSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
543e9a5e479SAndreas Jaekel 
544e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
545e9a5e479SAndreas Jaekel 		perror("removing queue failed");
546e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
547e9a5e479SAndreas Jaekel 	}
548e9a5e479SAndreas Jaekel 	return (0);
549e9a5e479SAndreas Jaekel }
550e9a5e479SAndreas Jaekel 
551e9a5e479SAndreas Jaekel static int
552e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
553e9a5e479SAndreas Jaekel {
554e9a5e479SAndreas Jaekel 	uint64_t maxqueuelen;
555e9a5e479SAndreas Jaekel 
556e9a5e479SAndreas Jaekel 	errno = 0;
557e9a5e479SAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
558e9a5e479SAndreas Jaekel 	if (errno) {
559e9a5e479SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
560e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
561e9a5e479SAndreas Jaekel 	}
562e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
563e9a5e479SAndreas Jaekel 		perror("setting max queue length failed");
564205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
565205a9bc9SAndreas Jaekel 	}
566205a9bc9SAndreas Jaekel 	return (0);
567205a9bc9SAndreas Jaekel }
568205a9bc9SAndreas Jaekel 
569205a9bc9SAndreas Jaekel static int
5702bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
5712bb8e5e2SAndreas Jaekel {
5722bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
5732bb8e5e2SAndreas Jaekel 	int len;
5742bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
5752bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
5762bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
5772bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
5782bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5792bb8e5e2SAndreas Jaekel 	}
5802bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
5812bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
5822bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
5832bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
5842bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5852bb8e5e2SAndreas Jaekel 	}
5862bb8e5e2SAndreas Jaekel 	return (0);
5872bb8e5e2SAndreas Jaekel }
5882bb8e5e2SAndreas Jaekel 
5892bb8e5e2SAndreas Jaekel int
5902bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
5912bb8e5e2SAndreas Jaekel {
5922bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
5932bb8e5e2SAndreas Jaekel }
5942bb8e5e2SAndreas Jaekel 
5952bb8e5e2SAndreas Jaekel int
5962bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
5972bb8e5e2SAndreas Jaekel {
5982bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
5992bb8e5e2SAndreas Jaekel }
6002bb8e5e2SAndreas Jaekel 
60101c2c787SAndreas Jaekel static int
602e9a5e479SAndreas Jaekel zev_debug_info(int fd)
603e9a5e479SAndreas Jaekel {
604e9a5e479SAndreas Jaekel 	zev_ioctl_debug_info_t di;
605e9a5e479SAndreas Jaekel 
606e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
607e9a5e479SAndreas Jaekel 		perror("getting zev debug info failed");
608e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
609e9a5e479SAndreas Jaekel 	}
610e9a5e479SAndreas Jaekel 
611e9a5e479SAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
612e9a5e479SAndreas Jaekel 	return 0;
613e9a5e479SAndreas Jaekel }
614e9a5e479SAndreas Jaekel 
615e9a5e479SAndreas Jaekel static int
61601c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
61701c2c787SAndreas Jaekel {
61801c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
61901c2c787SAndreas Jaekel 	uint64_t guid;
62001c2c787SAndreas Jaekel 	int len;
62101c2c787SAndreas Jaekel 	char *p;
62201c2c787SAndreas Jaekel 
62301c2c787SAndreas Jaekel 	p = strchr(arg, ':');
62401c2c787SAndreas Jaekel 	if (!p) {
62501c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
62601c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
62701c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
62801c2c787SAndreas Jaekel 	}
62901c2c787SAndreas Jaekel 	*p = '\n';
63001c2c787SAndreas Jaekel 	p++;
63101c2c787SAndreas Jaekel 
63201c2c787SAndreas Jaekel 	errno = 0;
633e9a5e479SAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
63401c2c787SAndreas Jaekel 	if (errno) {
63501c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
63601c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
63701c2c787SAndreas Jaekel 	}
63801c2c787SAndreas Jaekel 
63901c2c787SAndreas Jaekel 	len = strlen(p);
64001c2c787SAndreas Jaekel 
64101c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
64201c2c787SAndreas Jaekel 	if (!mark) {
64301c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
64401c2c787SAndreas Jaekel 		        strerror(errno));
64501c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
64601c2c787SAndreas Jaekel 	}
64701c2c787SAndreas Jaekel 	mark->zev_guid = guid;
64801c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
64901c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
65001c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
65101c2c787SAndreas Jaekel 
65201c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
65301c2c787SAndreas Jaekel 		perror("queueing mark failed");
65401c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
65501c2c787SAndreas Jaekel 	}
65601c2c787SAndreas Jaekel 
65701c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
65801c2c787SAndreas Jaekel 	return (0);
65901c2c787SAndreas Jaekel }
66001c2c787SAndreas Jaekel 
661e9a5e479SAndreas Jaekel static int
662e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
663e9a5e479SAndreas Jaekel {
664e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
665e9a5e479SAndreas Jaekel 
666*4ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
667*4ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
668e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
669e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
670e9a5e479SAndreas Jaekel 	}
671*4ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
672e9a5e479SAndreas Jaekel 
673e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
674e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
675e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
676e9a5e479SAndreas Jaekel 	}
677e9a5e479SAndreas Jaekel 	if (block) {
678e9a5e479SAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
679e9a5e479SAndreas Jaekel 	} else {
680e9a5e479SAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
681e9a5e479SAndreas Jaekel 	}
682e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
683e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
684e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
685e9a5e479SAndreas Jaekel 	}
686e9a5e479SAndreas Jaekel 	return (0);
687e9a5e479SAndreas Jaekel }
688e9a5e479SAndreas Jaekel 
689e9a5e479SAndreas Jaekel static int
690e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
691e9a5e479SAndreas Jaekel {
692e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
693e9a5e479SAndreas Jaekel 
694e9a5e479SAndreas Jaekel 	if (!len) {
695e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
696e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
697e9a5e479SAndreas Jaekel 	}
698e9a5e479SAndreas Jaekel 
699*4ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
700*4ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
701e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
702e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
703e9a5e479SAndreas Jaekel 	}
704*4ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
705e9a5e479SAndreas Jaekel 
706e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
707e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
708e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
709e9a5e479SAndreas Jaekel 	}
710e9a5e479SAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
711e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
712e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
713e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
714e9a5e479SAndreas Jaekel 	}
715e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
716e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
717e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
718e9a5e479SAndreas Jaekel 	}
719e9a5e479SAndreas Jaekel 
720e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
721e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
722e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
723e9a5e479SAndreas Jaekel 	}
724e9a5e479SAndreas Jaekel 	return (0);
725e9a5e479SAndreas Jaekel }
726e9a5e479SAndreas Jaekel 
727e9a5e479SAndreas Jaekel static int
728e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
729e9a5e479SAndreas Jaekel {
730e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
731e9a5e479SAndreas Jaekel 
732e9a5e479SAndreas Jaekel 	if (!len) {
733e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
734e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
735e9a5e479SAndreas Jaekel 	}
736e9a5e479SAndreas Jaekel 
737*4ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
738*4ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
739e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
740e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
741e9a5e479SAndreas Jaekel 	}
742*4ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
743e9a5e479SAndreas Jaekel 
744e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
745e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
746e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
747e9a5e479SAndreas Jaekel 	}
748e9a5e479SAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
749e9a5e479SAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
750e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
751e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
752e9a5e479SAndreas Jaekel 	}
753*4ca7dd5eSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
754e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
755e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
756e9a5e479SAndreas Jaekel 	}
757e9a5e479SAndreas Jaekel 
758e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
759e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
760e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
761e9a5e479SAndreas Jaekel 	}
762e9a5e479SAndreas Jaekel 	return (0);
763e9a5e479SAndreas Jaekel }
764e9a5e479SAndreas Jaekel 
765e9a5e479SAndreas Jaekel static int
766e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg)
767e9a5e479SAndreas Jaekel {
768e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
769e9a5e479SAndreas Jaekel 
770*4ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
771*4ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
772e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
773e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
774e9a5e479SAndreas Jaekel 	}
775*4ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
776e9a5e479SAndreas Jaekel 
777e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
778e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
779e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
780e9a5e479SAndreas Jaekel 	}
781e9a5e479SAndreas Jaekel 
782e9a5e479SAndreas Jaekel 	printf("queue        : %s\n", arg);
783e9a5e479SAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
784e9a5e479SAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
785e9a5e479SAndreas Jaekel 	printf("persistent   : %s\n",
786e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
787e9a5e479SAndreas Jaekel 	printf("blocking     : %s\n",
788e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
789e9a5e479SAndreas Jaekel 
790e9a5e479SAndreas Jaekel 	return (0);
791e9a5e479SAndreas Jaekel }
792e9a5e479SAndreas Jaekel 
793e9a5e479SAndreas Jaekel static int
794e9a5e479SAndreas Jaekel zev_list_queues(int fd)
795e9a5e479SAndreas Jaekel {
796e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
797e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
798e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
799e9a5e479SAndreas Jaekel 	uint64_t	i;
800e9a5e479SAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
801e9a5e479SAndreas Jaekel 
802e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
803e9a5e479SAndreas Jaekel 		perror("getting queue list failed");
804e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
805e9a5e479SAndreas Jaekel 	}
806e9a5e479SAndreas Jaekel 
807e9a5e479SAndreas Jaekel 	printf("Name                                     Size       "
808e9a5e479SAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
809e9a5e479SAndreas Jaekel 
810e9a5e479SAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
811e9a5e479SAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
812e9a5e479SAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
813e9a5e479SAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
814e9a5e479SAndreas Jaekel 
815*4ca7dd5eSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
816*4ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
817*4ca7dd5eSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
818*4ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
819e9a5e479SAndreas Jaekel 
820e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
821e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
822e9a5e479SAndreas Jaekel 				continue;
823e9a5e479SAndreas Jaekel 			perror("getting queue properties failed");
824e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
825e9a5e479SAndreas Jaekel 		}
826e9a5e479SAndreas Jaekel 
827*4ca7dd5eSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
828*4ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
829*4ca7dd5eSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
830*4ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
831e9a5e479SAndreas Jaekel 
832e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
833e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
834e9a5e479SAndreas Jaekel 				continue;
835e9a5e479SAndreas Jaekel 			perror("getting statistics data failed");
836e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
837e9a5e479SAndreas Jaekel 		}
838e9a5e479SAndreas Jaekel 
839e9a5e479SAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
840e9a5e479SAndreas Jaekel 		       " %-3s %-3s\n",
841e9a5e479SAndreas Jaekel 			name,
842e9a5e479SAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
843e9a5e479SAndreas Jaekel 			gqp.zev_max_queue_len,
844e9a5e479SAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
845e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
846e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
847e9a5e479SAndreas Jaekel 				 "yes" : "no");
848e9a5e479SAndreas Jaekel 	}
849e9a5e479SAndreas Jaekel 
850e9a5e479SAndreas Jaekel 	return (0);
851e9a5e479SAndreas Jaekel }
852e9a5e479SAndreas Jaekel 
8532bb8e5e2SAndreas Jaekel int
8542bb8e5e2SAndreas Jaekel main(int argc, char **argv)
8552bb8e5e2SAndreas Jaekel {
8562bb8e5e2SAndreas Jaekel 	int fd;
8572bb8e5e2SAndreas Jaekel 	int c;
8582bb8e5e2SAndreas Jaekel 	extern char *optarg;
859*4ca7dd5eSAndreas Jaekel 	int create_tmp_queue = 1;
860*4ca7dd5eSAndreas Jaekel 	char buf[MAXPATHLEN];
8612bb8e5e2SAndreas Jaekel 
8622bb8e5e2SAndreas Jaekel 	/* open device */
8632bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
8642bb8e5e2SAndreas Jaekel 	if (fd < 0) {
8652bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
8662bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
8672bb8e5e2SAndreas Jaekel 	}
868*4ca7dd5eSAndreas Jaekel 	while ((c = getopt(argc, argv,
869*4ca7dd5eSAndreas Jaekel 	                   "spd:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){
8702bb8e5e2SAndreas Jaekel 		switch(c) {
8712bb8e5e2SAndreas Jaekel 		case 's':
872e9a5e479SAndreas Jaekel 			return zev_statistics(fd);
8732bb8e5e2SAndreas Jaekel 		case 'p':
874*4ca7dd5eSAndreas Jaekel 			return zev_poll_events(fd, create_tmp_queue);
875e9a5e479SAndreas Jaekel 		case 'D':
876e9a5e479SAndreas Jaekel 			return zev_debug_info(fd);
8772bb8e5e2SAndreas Jaekel 		case 'd':
878e9a5e479SAndreas Jaekel 			close(fd);
8792bb8e5e2SAndreas Jaekel 			zev_device = optarg;
880e9a5e479SAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
881e9a5e479SAndreas Jaekel 			if (fd < 0) {
882e9a5e479SAndreas Jaekel 				perror("opening zev device failed");
883e9a5e479SAndreas Jaekel 				return EXIT_FAILURE;
884e9a5e479SAndreas Jaekel 			}
885*4ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
886*4ca7dd5eSAndreas Jaekel 			break;
887*4ca7dd5eSAndreas Jaekel 		case 'q':
888*4ca7dd5eSAndreas Jaekel 			snprintf(buf, sizeof(buf),
889*4ca7dd5eSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
890*4ca7dd5eSAndreas Jaekel 			close(fd);
891*4ca7dd5eSAndreas Jaekel 			zev_device = buf;
892*4ca7dd5eSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
893*4ca7dd5eSAndreas Jaekel 			if (fd < 0) {
894*4ca7dd5eSAndreas Jaekel 				perror("opening zev device failed");
895*4ca7dd5eSAndreas Jaekel 				return EXIT_FAILURE;
896*4ca7dd5eSAndreas Jaekel 			}
897*4ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
8982bb8e5e2SAndreas Jaekel 			break;
899e9a5e479SAndreas Jaekel 		case 'l':
900e9a5e479SAndreas Jaekel 			return zev_list_queues(fd);
901e9a5e479SAndreas Jaekel 		case 'Q':
902e9a5e479SAndreas Jaekel 			return zev_set_global_max_queue_len(fd, optarg);
903*4ca7dd5eSAndreas Jaekel 		case 'L':
904e9a5e479SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg, argv[optind]);
905205a9bc9SAndreas Jaekel 		case 't':
906e9a5e479SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg,
907e9a5e479SAndreas Jaekel 			                                     argv[optind]);
9082bb8e5e2SAndreas Jaekel 		case 'm':
9092bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
9102bb8e5e2SAndreas Jaekel 		case 'M':
9112bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
91201c2c787SAndreas Jaekel 		case 'k':
91301c2c787SAndreas Jaekel 			return zev_mark(fd, optarg);
914e9a5e479SAndreas Jaekel 		case 'a':
915*4ca7dd5eSAndreas Jaekel 			return zev_add_queue(fd, optarg, 0);
916*4ca7dd5eSAndreas Jaekel 		case 'A':
917*4ca7dd5eSAndreas Jaekel 			return zev_add_queue(fd, optarg, 1);
918e9a5e479SAndreas Jaekel 		case 'r':
919e9a5e479SAndreas Jaekel 			return zev_remove_queue(fd, optarg);
920e9a5e479SAndreas Jaekel 		case 'b':
921e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 0);
922e9a5e479SAndreas Jaekel 		case 'B':
923e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 1);
924e9a5e479SAndreas Jaekel 		case 'P':
925e9a5e479SAndreas Jaekel 			return zev_queue_properties(fd, optarg);
9262bb8e5e2SAndreas Jaekel 		case 'h':
9272bb8e5e2SAndreas Jaekel 		case '?':
9282bb8e5e2SAndreas Jaekel 		default:
9292bb8e5e2SAndreas Jaekel 			usage(argv[0]);
9302bb8e5e2SAndreas Jaekel 		}
9312bb8e5e2SAndreas Jaekel 	}
9322bb8e5e2SAndreas Jaekel 	usage(argv[0]);
9332bb8e5e2SAndreas Jaekel 	close(fd);
934e9a5e479SAndreas Jaekel 	return EXIT_FAILURE;
9352bb8e5e2SAndreas Jaekel }
9362bb8e5e2SAndreas Jaekel 
937