xref: /titanic_52/usr/src/cmd/zevadm/zevadm.c (revision e9a5e4794d4aeafec64f1e4e45089cb38df36962)
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)
16*e9a5e479SAndreas Jaekel #define OP_DEBUG_INFO		(1 << 5)
172bb8e5e2SAndreas Jaekel 
18*e9a5e479SAndreas 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 
45*e9a5e479SAndreas Jaekel static int
462bb8e5e2SAndreas Jaekel zev_statistics(int fd)
472bb8e5e2SAndreas Jaekel {
482bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
49*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
502bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
51*e9a5e479SAndreas 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 
60*e9a5e479SAndreas Jaekel 	printf("    discarded events        : %lu\n",
61*e9a5e479SAndreas Jaekel 	    zs.zev_cnt_discarded_events);
62*e9a5e479SAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
63*e9a5e479SAndreas 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);
83*e9a5e479SAndreas 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 
393*e9a5e479SAndreas Jaekel static int
3942bb8e5e2SAndreas Jaekel zev_poll_events(int fd)
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;
401*e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
402*e9a5e479SAndreas Jaekel 	int q_fd;
403*e9a5e479SAndreas Jaekel 
404*e9a5e479SAndreas Jaekel 	/* create temporary queue */
405*e9a5e479SAndreas Jaekel 	aq.zev_max_queue_len = 0;
406*e9a5e479SAndreas Jaekel 	aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
407*e9a5e479SAndreas Jaekel 	snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
408*e9a5e479SAndreas Jaekel 	         "zevadm.%ld.%ld", time(NULL), getpid());
409*e9a5e479SAndreas Jaekel 	aq.zev_namelen = strlen(aq.zev_name);
410*e9a5e479SAndreas Jaekel 
411*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
412*e9a5e479SAndreas Jaekel 		perror("adding temporary queue failed");
413*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
414*e9a5e479SAndreas Jaekel 	}
415*e9a5e479SAndreas Jaekel 
416*e9a5e479SAndreas Jaekel 	snprintf(buf, sizeof(buf), "/devices/pseudo/zev@0:%s", aq.zev_name);
417*e9a5e479SAndreas Jaekel 	q_fd = open(buf, O_RDONLY);
418*e9a5e479SAndreas Jaekel 	if (q_fd < 0) {
419*e9a5e479SAndreas Jaekel 		perror("opening queue device failed");
420*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
421*e9a5e479SAndreas Jaekel 	}
422*e9a5e479SAndreas Jaekel 
4232bb8e5e2SAndreas Jaekel 	while (1) {
424*e9a5e479SAndreas Jaekel 		pfd[0].fd = q_fd;
4252bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
4262bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
4272bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4282bb8e5e2SAndreas Jaekel 			perror("poll failed");
429*e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4302bb8e5e2SAndreas Jaekel 		}
4312bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
4322bb8e5e2SAndreas Jaekel 			continue;
4332bb8e5e2SAndreas Jaekel 		/* data available */
434*e9a5e479SAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
4352bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4362bb8e5e2SAndreas Jaekel 			perror("read failed");
437*e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4382bb8e5e2SAndreas Jaekel 		}
4392bb8e5e2SAndreas Jaekel 		if (ret == 0)
4402bb8e5e2SAndreas Jaekel 			continue;
44168a46c64SAndreas Jaekel 		while (ret > off) {
44268a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
44368a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
44468a46c64SAndreas Jaekel 			off += ev->header.record_len;
44568a46c64SAndreas Jaekel 		}
446108668daSAndreas Jaekel 		off = 0;
4472bb8e5e2SAndreas Jaekel 	}
448*e9a5e479SAndreas Jaekel 	close(q_fd);
449*e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
4502bb8e5e2SAndreas Jaekel }
4512bb8e5e2SAndreas Jaekel 
4522bb8e5e2SAndreas Jaekel static void
4532bb8e5e2SAndreas Jaekel usage(char *progname)
4542bb8e5e2SAndreas Jaekel {
455*e9a5e479SAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
456*e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
457*e9a5e479SAndreas Jaekel 	fprintf(stderr, " Status information:\n");
4582bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
4592bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
460*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
461*e9a5e479SAndreas Jaekel 	        "information\n");
462*e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
463*e9a5e479SAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
464*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
465*e9a5e479SAndreas Jaekel 	        "length\n");
466*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
467*e9a5e479SAndreas Jaekel 	        "this pool\n");
4682bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
469*e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
470*e9a5e479SAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
471*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
472*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -a <name>            add queue\n");
473*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
474*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
475*e9a5e479SAndreas Jaekel 	        "(default)\n");
476*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
477*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
478*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -q <name> <bytes>    set maximum event queue "
479*e9a5e479SAndreas Jaekel 	        "length\n");
480*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
481*e9a5e479SAndreas Jaekel 	        "throttle\n");
482*e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
483*e9a5e479SAndreas Jaekel 	fprintf(stderr, " Other options:\n");
484*e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
485*e9a5e479SAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
48601c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
4872bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
4882bb8e5e2SAndreas Jaekel }
4892bb8e5e2SAndreas Jaekel 
4902bb8e5e2SAndreas Jaekel static int
491*e9a5e479SAndreas Jaekel zev_add_queue(int fd, char *arg)
4922bb8e5e2SAndreas Jaekel {
493*e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
494*e9a5e479SAndreas Jaekel 	int namelen;
4952bb8e5e2SAndreas Jaekel 
496*e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
497*e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
498*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
4992bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5002bb8e5e2SAndreas Jaekel 	}
501*e9a5e479SAndreas Jaekel 
502*e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
503*e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
504*e9a5e479SAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;  /* non-blocking, but persistent */
505*e9a5e479SAndreas Jaekel 	aq.zev_max_queue_len = (1024 * 1024);
506*e9a5e479SAndreas Jaekel 
507*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
508*e9a5e479SAndreas Jaekel 		perror("adding queue failed");
5092bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5102bb8e5e2SAndreas Jaekel 	}
5112bb8e5e2SAndreas Jaekel 	return (0);
5122bb8e5e2SAndreas Jaekel }
5132bb8e5e2SAndreas Jaekel 
5142bb8e5e2SAndreas Jaekel static int
515*e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg)
516205a9bc9SAndreas Jaekel {
517*e9a5e479SAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
518*e9a5e479SAndreas Jaekel 	int namelen;
519205a9bc9SAndreas Jaekel 
520*e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
521*e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
522*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
523205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
524205a9bc9SAndreas Jaekel 	}
525*e9a5e479SAndreas Jaekel 
526*e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
527*e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
528*e9a5e479SAndreas Jaekel 
529*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
530*e9a5e479SAndreas Jaekel 		perror("removing queue failed");
531*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
532*e9a5e479SAndreas Jaekel 	}
533*e9a5e479SAndreas Jaekel 	return (0);
534*e9a5e479SAndreas Jaekel }
535*e9a5e479SAndreas Jaekel 
536*e9a5e479SAndreas Jaekel static int
537*e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
538*e9a5e479SAndreas Jaekel {
539*e9a5e479SAndreas Jaekel 	uint64_t maxqueuelen;
540*e9a5e479SAndreas Jaekel 
541*e9a5e479SAndreas Jaekel 	errno = 0;
542*e9a5e479SAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
543*e9a5e479SAndreas Jaekel 	if (errno) {
544*e9a5e479SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
545*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
546*e9a5e479SAndreas Jaekel 	}
547*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
548*e9a5e479SAndreas Jaekel 		perror("setting max queue length failed");
549205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
550205a9bc9SAndreas Jaekel 	}
551205a9bc9SAndreas Jaekel 	return (0);
552205a9bc9SAndreas Jaekel }
553205a9bc9SAndreas Jaekel 
554205a9bc9SAndreas Jaekel static int
5552bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
5562bb8e5e2SAndreas Jaekel {
5572bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
5582bb8e5e2SAndreas Jaekel 	int len;
5592bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
5602bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
5612bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
5622bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
5632bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5642bb8e5e2SAndreas Jaekel 	}
5652bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
5662bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
5672bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
5682bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
5692bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5702bb8e5e2SAndreas Jaekel 	}
5712bb8e5e2SAndreas Jaekel 	return (0);
5722bb8e5e2SAndreas Jaekel }
5732bb8e5e2SAndreas Jaekel 
5742bb8e5e2SAndreas Jaekel int
5752bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
5762bb8e5e2SAndreas Jaekel {
5772bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
5782bb8e5e2SAndreas Jaekel }
5792bb8e5e2SAndreas Jaekel 
5802bb8e5e2SAndreas Jaekel int
5812bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
5822bb8e5e2SAndreas Jaekel {
5832bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
5842bb8e5e2SAndreas Jaekel }
5852bb8e5e2SAndreas Jaekel 
58601c2c787SAndreas Jaekel static int
587*e9a5e479SAndreas Jaekel zev_debug_info(int fd)
588*e9a5e479SAndreas Jaekel {
589*e9a5e479SAndreas Jaekel 	zev_ioctl_debug_info_t di;
590*e9a5e479SAndreas Jaekel 
591*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
592*e9a5e479SAndreas Jaekel 		perror("getting zev debug info failed");
593*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
594*e9a5e479SAndreas Jaekel 	}
595*e9a5e479SAndreas Jaekel 
596*e9a5e479SAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
597*e9a5e479SAndreas Jaekel 	return 0;
598*e9a5e479SAndreas Jaekel }
599*e9a5e479SAndreas Jaekel 
600*e9a5e479SAndreas Jaekel static int
60101c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
60201c2c787SAndreas Jaekel {
60301c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
60401c2c787SAndreas Jaekel 	uint64_t guid;
60501c2c787SAndreas Jaekel 	int len;
60601c2c787SAndreas Jaekel 	char *p;
60701c2c787SAndreas Jaekel 
60801c2c787SAndreas Jaekel 	p = strchr(arg, ':');
60901c2c787SAndreas Jaekel 	if (!p) {
61001c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
61101c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
61201c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
61301c2c787SAndreas Jaekel 	}
61401c2c787SAndreas Jaekel 	*p = '\n';
61501c2c787SAndreas Jaekel 	p++;
61601c2c787SAndreas Jaekel 
61701c2c787SAndreas Jaekel 	errno = 0;
618*e9a5e479SAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
61901c2c787SAndreas Jaekel 	if (errno) {
62001c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
62101c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
62201c2c787SAndreas Jaekel 	}
62301c2c787SAndreas Jaekel 
62401c2c787SAndreas Jaekel 	len = strlen(p);
62501c2c787SAndreas Jaekel 
62601c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
62701c2c787SAndreas Jaekel 	if (!mark) {
62801c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
62901c2c787SAndreas Jaekel 		        strerror(errno));
63001c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
63101c2c787SAndreas Jaekel 	}
63201c2c787SAndreas Jaekel 	mark->zev_guid = guid;
63301c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
63401c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
63501c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
63601c2c787SAndreas Jaekel 
63701c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
63801c2c787SAndreas Jaekel 		perror("queueing mark failed");
63901c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
64001c2c787SAndreas Jaekel 	}
64101c2c787SAndreas Jaekel 
64201c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
64301c2c787SAndreas Jaekel 	return (0);
64401c2c787SAndreas Jaekel }
64501c2c787SAndreas Jaekel 
646*e9a5e479SAndreas Jaekel static int
647*e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
648*e9a5e479SAndreas Jaekel {
649*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
650*e9a5e479SAndreas Jaekel 
651*e9a5e479SAndreas Jaekel 	gqp.zev_namelen = strlen(arg);
652*e9a5e479SAndreas Jaekel 	if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
653*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
654*e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
655*e9a5e479SAndreas Jaekel 	}
656*e9a5e479SAndreas Jaekel 	strcpy(gqp.zev_name, arg);
657*e9a5e479SAndreas Jaekel 
658*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
659*e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
660*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
661*e9a5e479SAndreas Jaekel 	}
662*e9a5e479SAndreas Jaekel 	if (block) {
663*e9a5e479SAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
664*e9a5e479SAndreas Jaekel 	} else {
665*e9a5e479SAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
666*e9a5e479SAndreas Jaekel 	}
667*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
668*e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
669*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
670*e9a5e479SAndreas Jaekel 	}
671*e9a5e479SAndreas Jaekel 	return (0);
672*e9a5e479SAndreas Jaekel }
673*e9a5e479SAndreas Jaekel 
674*e9a5e479SAndreas Jaekel static int
675*e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
676*e9a5e479SAndreas Jaekel {
677*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
678*e9a5e479SAndreas Jaekel 
679*e9a5e479SAndreas Jaekel 	if (!len) {
680*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
681*e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
682*e9a5e479SAndreas Jaekel 	}
683*e9a5e479SAndreas Jaekel 
684*e9a5e479SAndreas Jaekel 	gqp.zev_namelen = strlen(arg);
685*e9a5e479SAndreas Jaekel 	if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
686*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
687*e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
688*e9a5e479SAndreas Jaekel 	}
689*e9a5e479SAndreas Jaekel 	strcpy(gqp.zev_name, arg);
690*e9a5e479SAndreas Jaekel 
691*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
692*e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
693*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
694*e9a5e479SAndreas Jaekel 	}
695*e9a5e479SAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
696*e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
697*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
698*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
699*e9a5e479SAndreas Jaekel 	}
700*e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
701*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
702*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
703*e9a5e479SAndreas Jaekel 	}
704*e9a5e479SAndreas Jaekel 
705*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
706*e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
707*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
708*e9a5e479SAndreas Jaekel 	}
709*e9a5e479SAndreas Jaekel 	return (0);
710*e9a5e479SAndreas Jaekel }
711*e9a5e479SAndreas Jaekel 
712*e9a5e479SAndreas Jaekel static int
713*e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
714*e9a5e479SAndreas Jaekel {
715*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
716*e9a5e479SAndreas Jaekel 
717*e9a5e479SAndreas Jaekel 	if (!len) {
718*e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
719*e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
720*e9a5e479SAndreas Jaekel 	}
721*e9a5e479SAndreas Jaekel 
722*e9a5e479SAndreas Jaekel 	gqp.zev_namelen = strlen(arg);
723*e9a5e479SAndreas Jaekel 	if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
724*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
725*e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
726*e9a5e479SAndreas Jaekel 	}
727*e9a5e479SAndreas Jaekel 	strcpy(gqp.zev_name, arg);
728*e9a5e479SAndreas Jaekel 
729*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
730*e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
731*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
732*e9a5e479SAndreas Jaekel 	}
733*e9a5e479SAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
734*e9a5e479SAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
735*e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
736*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
737*e9a5e479SAndreas Jaekel 	}
738*e9a5e479SAndreas Jaekel 	if ((gqp.zev_poll_wakeup_threshold < ZEV_MIN_POLL_WAKEUP_QUEUE_LEN) ||
739*e9a5e479SAndreas Jaekel 	    (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN)) {
740*e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
741*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
742*e9a5e479SAndreas Jaekel 	}
743*e9a5e479SAndreas Jaekel 
744*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
745*e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
746*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
747*e9a5e479SAndreas Jaekel 	}
748*e9a5e479SAndreas Jaekel 	return (0);
749*e9a5e479SAndreas Jaekel }
750*e9a5e479SAndreas Jaekel 
751*e9a5e479SAndreas Jaekel static int
752*e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg)
753*e9a5e479SAndreas Jaekel {
754*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
755*e9a5e479SAndreas Jaekel 
756*e9a5e479SAndreas Jaekel 	gqp.zev_namelen = strlen(arg);
757*e9a5e479SAndreas Jaekel 	if (gqp.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
758*e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
759*e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
760*e9a5e479SAndreas Jaekel 	}
761*e9a5e479SAndreas Jaekel 	strcpy(gqp.zev_name, arg);
762*e9a5e479SAndreas Jaekel 
763*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
764*e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
765*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
766*e9a5e479SAndreas Jaekel 	}
767*e9a5e479SAndreas Jaekel 
768*e9a5e479SAndreas Jaekel 	printf("queue        : %s\n", arg);
769*e9a5e479SAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
770*e9a5e479SAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
771*e9a5e479SAndreas Jaekel 	printf("persistent   : %s\n",
772*e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
773*e9a5e479SAndreas Jaekel 	printf("blocking     : %s\n",
774*e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
775*e9a5e479SAndreas Jaekel 
776*e9a5e479SAndreas Jaekel 	return (0);
777*e9a5e479SAndreas Jaekel }
778*e9a5e479SAndreas Jaekel 
779*e9a5e479SAndreas Jaekel static int
780*e9a5e479SAndreas Jaekel zev_list_queues(int fd)
781*e9a5e479SAndreas Jaekel {
782*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
783*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
784*e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
785*e9a5e479SAndreas Jaekel 	uint64_t	i;
786*e9a5e479SAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
787*e9a5e479SAndreas Jaekel 
788*e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
789*e9a5e479SAndreas Jaekel 		perror("getting queue list failed");
790*e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
791*e9a5e479SAndreas Jaekel 	}
792*e9a5e479SAndreas Jaekel 
793*e9a5e479SAndreas Jaekel 	printf("Name                                     Size       "
794*e9a5e479SAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
795*e9a5e479SAndreas Jaekel 
796*e9a5e479SAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
797*e9a5e479SAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
798*e9a5e479SAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
799*e9a5e479SAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
800*e9a5e479SAndreas Jaekel 
801*e9a5e479SAndreas Jaekel 		memcpy(gqp.zev_name, gql.zev_queue_name[i].zev_name,
802*e9a5e479SAndreas Jaekel 		       ZEV_MAX_QUEUE_NAME_LEN);
803*e9a5e479SAndreas Jaekel 		gqp.zev_namelen = gql.zev_queue_name[i].zev_namelen;
804*e9a5e479SAndreas Jaekel 
805*e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
806*e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
807*e9a5e479SAndreas Jaekel 				continue;
808*e9a5e479SAndreas Jaekel 			perror("getting queue properties failed");
809*e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
810*e9a5e479SAndreas Jaekel 		}
811*e9a5e479SAndreas Jaekel 
812*e9a5e479SAndreas Jaekel 		memcpy(gs.zev_name, gql.zev_queue_name[i].zev_name,
813*e9a5e479SAndreas Jaekel 		       ZEV_MAX_QUEUE_NAME_LEN);
814*e9a5e479SAndreas Jaekel 		gs.zev_namelen = gql.zev_queue_name[i].zev_namelen;
815*e9a5e479SAndreas Jaekel 
816*e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
817*e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
818*e9a5e479SAndreas Jaekel 				continue;
819*e9a5e479SAndreas Jaekel 			perror("getting statistics data failed");
820*e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
821*e9a5e479SAndreas Jaekel 		}
822*e9a5e479SAndreas Jaekel 
823*e9a5e479SAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
824*e9a5e479SAndreas Jaekel 		       " %-3s %-3s\n",
825*e9a5e479SAndreas Jaekel 			name,
826*e9a5e479SAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
827*e9a5e479SAndreas Jaekel 			gqp.zev_max_queue_len,
828*e9a5e479SAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
829*e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
830*e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
831*e9a5e479SAndreas Jaekel 				 "yes" : "no");
832*e9a5e479SAndreas Jaekel 	}
833*e9a5e479SAndreas Jaekel 
834*e9a5e479SAndreas Jaekel 	return (0);
835*e9a5e479SAndreas Jaekel }
836*e9a5e479SAndreas Jaekel 
8372bb8e5e2SAndreas Jaekel int
8382bb8e5e2SAndreas Jaekel main(int argc, char **argv)
8392bb8e5e2SAndreas Jaekel {
8402bb8e5e2SAndreas Jaekel 	int fd;
8412bb8e5e2SAndreas Jaekel 	int c;
8422bb8e5e2SAndreas Jaekel 	extern char *optarg;
8432bb8e5e2SAndreas Jaekel 
8442bb8e5e2SAndreas Jaekel 	/* open device */
8452bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
8462bb8e5e2SAndreas Jaekel 	if (fd < 0) {
8472bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
8482bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
8492bb8e5e2SAndreas Jaekel 	}
850*e9a5e479SAndreas Jaekel 	while ((c = getopt(argc, argv, "spd:Dlk:q:Qt:m:M:a:r:P:b:B:h?")) != -1){
8512bb8e5e2SAndreas Jaekel 		switch(c) {
8522bb8e5e2SAndreas Jaekel 		case 's':
853*e9a5e479SAndreas Jaekel 			return zev_statistics(fd);
8542bb8e5e2SAndreas Jaekel 		case 'p':
855*e9a5e479SAndreas Jaekel 			return zev_poll_events(fd);
856*e9a5e479SAndreas Jaekel 		case 'D':
857*e9a5e479SAndreas Jaekel 			return zev_debug_info(fd);
8582bb8e5e2SAndreas Jaekel 		case 'd':
859*e9a5e479SAndreas Jaekel 			close(fd);
8602bb8e5e2SAndreas Jaekel 			zev_device = optarg;
861*e9a5e479SAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
862*e9a5e479SAndreas Jaekel 			if (fd < 0) {
863*e9a5e479SAndreas Jaekel 				perror("opening zev device failed");
864*e9a5e479SAndreas Jaekel 				return EXIT_FAILURE;
865*e9a5e479SAndreas Jaekel 			}
8662bb8e5e2SAndreas Jaekel 			break;
867*e9a5e479SAndreas Jaekel 		case 'l':
868*e9a5e479SAndreas Jaekel 			return zev_list_queues(fd);
869*e9a5e479SAndreas Jaekel 		case 'Q':
870*e9a5e479SAndreas Jaekel 			return zev_set_global_max_queue_len(fd, optarg);
8712bb8e5e2SAndreas Jaekel 		case 'q':
872*e9a5e479SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg, argv[optind]);
873205a9bc9SAndreas Jaekel 		case 't':
874*e9a5e479SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg,
875*e9a5e479SAndreas Jaekel 			                                     argv[optind]);
8762bb8e5e2SAndreas Jaekel 		case 'm':
8772bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
8782bb8e5e2SAndreas Jaekel 		case 'M':
8792bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
88001c2c787SAndreas Jaekel 		case 'k':
88101c2c787SAndreas Jaekel 			return zev_mark(fd, optarg);
882*e9a5e479SAndreas Jaekel 		case 'a':
883*e9a5e479SAndreas Jaekel 			return zev_add_queue(fd, optarg);
884*e9a5e479SAndreas Jaekel 		case 'r':
885*e9a5e479SAndreas Jaekel 			return zev_remove_queue(fd, optarg);
886*e9a5e479SAndreas Jaekel 		case 'b':
887*e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 0);
888*e9a5e479SAndreas Jaekel 		case 'B':
889*e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 1);
890*e9a5e479SAndreas Jaekel 		case 'P':
891*e9a5e479SAndreas Jaekel 			return zev_queue_properties(fd, optarg);
8922bb8e5e2SAndreas Jaekel 		case 'h':
8932bb8e5e2SAndreas Jaekel 		case '?':
8942bb8e5e2SAndreas Jaekel 		default:
8952bb8e5e2SAndreas Jaekel 			usage(argv[0]);
8962bb8e5e2SAndreas Jaekel 		}
8972bb8e5e2SAndreas Jaekel 	}
8982bb8e5e2SAndreas Jaekel 	usage(argv[0]);
8992bb8e5e2SAndreas Jaekel 	close(fd);
900*e9a5e479SAndreas Jaekel 	return EXIT_FAILURE;
9012bb8e5e2SAndreas Jaekel }
9022bb8e5e2SAndreas Jaekel 
903