xref: /titanic_53/usr/src/cmd/zevadm/zevadm.c (revision 5e28636192c7a7f235ea1e835192fe00d17757cb)
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 
45*5e286361SAndreas Jaekel static int verbose = 0;
46*5e286361SAndreas Jaekel 
47e9a5e479SAndreas Jaekel static int
482bb8e5e2SAndreas Jaekel zev_statistics(int fd)
492bb8e5e2SAndreas Jaekel {
502bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
51e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
522bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
53e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
542bb8e5e2SAndreas Jaekel 	}
552bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
562bb8e5e2SAndreas Jaekel 
572bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
582bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
592bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
602bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
612bb8e5e2SAndreas Jaekel 
62e9a5e479SAndreas Jaekel 	printf("    discarded events        : %lu\n",
63e9a5e479SAndreas Jaekel 	    zs.zev_cnt_discarded_events);
64e9a5e479SAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
65e9a5e479SAndreas Jaekel 
662bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
672bb8e5e2SAndreas Jaekel 
682bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
692bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
702bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
712bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
722bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
732bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
742bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
752bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
762bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
772bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
782bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
792bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
802bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
812bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
822bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
832bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
842bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
85e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
862bb8e5e2SAndreas Jaekel }
872bb8e5e2SAndreas Jaekel 
882bb8e5e2SAndreas Jaekel static void
8963aba447SAndreas Jaekel zev_print_error(char *buf)
9063aba447SAndreas Jaekel {
9163aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
9263aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
9363aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
9463aba447SAndreas Jaekel 
9563aba447SAndreas Jaekel 	printf("%s %s: failed_op=%s msg=%s\n",
9663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
9763aba447SAndreas Jaekel 	       zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec));
9863aba447SAndreas Jaekel }
9963aba447SAndreas Jaekel 
10063aba447SAndreas Jaekel static void
10101c2c787SAndreas Jaekel zev_print_mark(char *buf)
10201c2c787SAndreas Jaekel {
10301c2c787SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
10401c2c787SAndreas Jaekel 	time_t op_time = rec->op_time;
10501c2c787SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
10601c2c787SAndreas Jaekel 
10701c2c787SAndreas Jaekel 	printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
10801c2c787SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id,
10901c2c787SAndreas Jaekel 	       rec->payload_len);
11001c2c787SAndreas Jaekel }
11101c2c787SAndreas Jaekel 
11201c2c787SAndreas Jaekel static void
11363aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
11463aba447SAndreas Jaekel {
11563aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
11663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
11763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
11863aba447SAndreas Jaekel 
11963aba447SAndreas Jaekel 	printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n",
12063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
12163aba447SAndreas Jaekel 	       rec->guid,
12263aba447SAndreas Jaekel 	       rec->remount ? "true" : "false",
12363aba447SAndreas Jaekel 	       ZEV_DATASET(rec),
12463aba447SAndreas Jaekel 	       ZEV_MOUNTPOINT(rec));
12563aba447SAndreas Jaekel }
12663aba447SAndreas Jaekel 
12763aba447SAndreas Jaekel static void
12863aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
12963aba447SAndreas Jaekel {
13063aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
13163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
13263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
13363aba447SAndreas Jaekel 
13463aba447SAndreas Jaekel 	printf("%s %s: guid=%llu\n",
13563aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
13663aba447SAndreas Jaekel 	       rec->guid);
13763aba447SAndreas Jaekel }
13863aba447SAndreas Jaekel 
13963aba447SAndreas Jaekel static void
14063aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
14163aba447SAndreas Jaekel {
14263aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
14363aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
14463aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
14563aba447SAndreas Jaekel 
14663aba447SAndreas Jaekel 	printf("%s %s: guid=%llu offset=%llu length=%llu\n",
14763aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
14863aba447SAndreas Jaekel 	       rec->guid,
14963aba447SAndreas Jaekel 	       rec->offset,
15063aba447SAndreas Jaekel 	       rec->length);
15163aba447SAndreas Jaekel }
15263aba447SAndreas Jaekel 
15363aba447SAndreas Jaekel static void
15463aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
15563aba447SAndreas Jaekel {
15663aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
15763aba447SAndreas Jaekel }
15863aba447SAndreas Jaekel 
15963aba447SAndreas Jaekel static void
16063aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
16163aba447SAndreas Jaekel {
16263aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
16363aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
16463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
16563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
16663aba447SAndreas Jaekel 
16763aba447SAndreas Jaekel 	printf("%s %s: guid=%llu file=%llu.%llu\n",
16863aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
16963aba447SAndreas Jaekel 	       rec->guid,
17063aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
17163aba447SAndreas Jaekel }
17263aba447SAndreas Jaekel 
17363aba447SAndreas Jaekel static void
17463aba447SAndreas Jaekel zev_print_znode_create(char *buf)
17563aba447SAndreas Jaekel {
17663aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
17763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
17863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
17963aba447SAndreas Jaekel 
180c035b1e8SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
181c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
18263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
18363aba447SAndreas Jaekel 	       rec->guid,
18463aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
18563aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
186c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->parent.mtime,
18763aba447SAndreas Jaekel 	       ZEV_NAME(rec));
18863aba447SAndreas Jaekel }
18963aba447SAndreas Jaekel 
19063aba447SAndreas Jaekel static void
19163aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
19263aba447SAndreas Jaekel {
19363aba447SAndreas Jaekel 	zev_print_znode_create(buf);
19463aba447SAndreas Jaekel }
19563aba447SAndreas Jaekel 
19663aba447SAndreas Jaekel static void
19763aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
19863aba447SAndreas Jaekel {
19963aba447SAndreas Jaekel 	zev_print_znode_create(buf);
20063aba447SAndreas Jaekel }
20163aba447SAndreas Jaekel 
20263aba447SAndreas Jaekel static void
20363aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
20463aba447SAndreas Jaekel {
20563aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
20663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
20763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
20863aba447SAndreas Jaekel 
2096db5d4ecSAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n",
21063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
21163aba447SAndreas Jaekel 	       rec->guid,
21263aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
2136db5d4ecSAndreas Jaekel 	       rec->file.mtime,
21463aba447SAndreas Jaekel 	       ZEV_NAME(rec));
21563aba447SAndreas Jaekel }
21663aba447SAndreas Jaekel 
21763aba447SAndreas Jaekel static void
21863aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
21963aba447SAndreas Jaekel {
22063aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
22163aba447SAndreas Jaekel }
22263aba447SAndreas Jaekel 
22363aba447SAndreas Jaekel static void
22463aba447SAndreas Jaekel zev_print_znode_link(char *buf)
22563aba447SAndreas Jaekel {
22663aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
22763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
22863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
22963aba447SAndreas Jaekel 
23003101f54SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu "
23103101f54SAndreas Jaekel 	       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
23263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
23363aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
23463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
23503101f54SAndreas Jaekel 	       rec->file.ctime, rec->parent.ctime,
23663aba447SAndreas Jaekel 	       ZEV_NAME(rec));
23763aba447SAndreas Jaekel 	printf("links: %d\n", rec->file.links);
23863aba447SAndreas Jaekel }
23963aba447SAndreas Jaekel 
24063aba447SAndreas Jaekel static void
24163aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
24263aba447SAndreas Jaekel {
24363aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
24463aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
24563aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
24663aba447SAndreas Jaekel 
24763aba447SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n",
24863aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
24963aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
25063aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
25163aba447SAndreas Jaekel 	       ZEV_NAME(rec),
25263aba447SAndreas Jaekel 	       ZEV_LINK(rec));
25363aba447SAndreas Jaekel }
25463aba447SAndreas Jaekel 
25563aba447SAndreas Jaekel static void
25663aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
25763aba447SAndreas Jaekel {
25863aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
25963aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
26063aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
26163aba447SAndreas Jaekel 
26263aba447SAndreas Jaekel 	printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu "
263c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, "
264c035b1e8SAndreas Jaekel 	       "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, "
26563aba447SAndreas Jaekel 	       "srcname='%s' dstname='%s'\n",
26663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
26763aba447SAndreas Jaekel 	       rec->srcdir.ino, rec->srcdir.gen,
26863aba447SAndreas Jaekel 	       rec->dstdir.ino, rec->dstdir.gen,
26963aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
270c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->file.ctime,
271c035b1e8SAndreas Jaekel 	       rec->srcdir.mtime, rec->srcdir.ctime,
272c035b1e8SAndreas Jaekel 	       rec->dstdir.mtime, rec->dstdir.ctime,
27363aba447SAndreas Jaekel 	       ZEV_SRCNAME(rec),
27463aba447SAndreas Jaekel 	       ZEV_DSTNAME(rec));
27563aba447SAndreas Jaekel }
27663aba447SAndreas Jaekel 
27763aba447SAndreas Jaekel static void
278*5e286361SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
279*5e286361SAndreas Jaekel {
280*5e286361SAndreas Jaekel 	int     i;
281*5e286361SAndreas Jaekel 
282*5e286361SAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
283*5e286361SAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
284*5e286361SAndreas Jaekel 	}
285*5e286361SAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
286*5e286361SAndreas Jaekel }
287*5e286361SAndreas Jaekel 
288*5e286361SAndreas Jaekel static void
28963aba447SAndreas Jaekel zev_print_znode_write(char *buf)
29063aba447SAndreas Jaekel {
29163aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
29263aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
29363aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
294*5e286361SAndreas Jaekel 	zev_sig_t *sig;
295*5e286361SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
296*5e286361SAndreas Jaekel 	int i;
29763aba447SAndreas Jaekel 
29863aba447SAndreas Jaekel 	printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
29963aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
30063aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
30163aba447SAndreas Jaekel 	       rec->offset, rec->length);
302*5e286361SAndreas Jaekel 	if (verbose) {
303*5e286361SAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
304*5e286361SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
305*5e286361SAndreas Jaekel 			sig += i;
306*5e286361SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
307*5e286361SAndreas Jaekel 			printf("  sig: level %d, offset %llu, value %s\n",
308*5e286361SAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
309*5e286361SAndreas Jaekel 		}
310*5e286361SAndreas Jaekel 	}
31163aba447SAndreas Jaekel }
31263aba447SAndreas Jaekel 
31363aba447SAndreas Jaekel static void
31463aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
31563aba447SAndreas Jaekel {
31663aba447SAndreas Jaekel 	zev_print_znode_write(buf);
31763aba447SAndreas Jaekel }
31863aba447SAndreas Jaekel 
31963aba447SAndreas Jaekel static void
32063aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
32163aba447SAndreas Jaekel {
32263aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
32363aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
32463aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
32563aba447SAndreas Jaekel 
326c035b1e8SAndreas Jaekel 	printf("%s %s: file=%llu.%llu mtime=%llu\n",
32763aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
328c035b1e8SAndreas Jaekel 	       rec->file.ino, rec->file.gen, rec->file.mtime);
32963aba447SAndreas Jaekel }
33063aba447SAndreas Jaekel 
33163aba447SAndreas Jaekel static void
33263aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
33363aba447SAndreas Jaekel {
33463aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
33563aba447SAndreas Jaekel }
33663aba447SAndreas Jaekel 
33763aba447SAndreas Jaekel static void
3389193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
3399193e9c2SAndreas Jaekel {
34063aba447SAndreas Jaekel 	int record_len;
34163aba447SAndreas Jaekel 	int op;
3429193e9c2SAndreas Jaekel 
34363aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
34463aba447SAndreas Jaekel 	if (record_len != len) {
34563aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
34663aba447SAndreas Jaekel 		        record_len, len);
3479193e9c2SAndreas Jaekel 		exit(1);
3489193e9c2SAndreas Jaekel 	}
34963aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
3509193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
35163aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
3529193e9c2SAndreas Jaekel 		exit(1);
3539193e9c2SAndreas Jaekel 	}
35463aba447SAndreas Jaekel 	switch (op) {
35563aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
35663aba447SAndreas Jaekel 		zev_print_error(buf);
3579193e9c2SAndreas Jaekel 		break;
35801c2c787SAndreas Jaekel 	case ZEV_OP_MARK:
35901c2c787SAndreas Jaekel 		zev_print_mark(buf);
36001c2c787SAndreas Jaekel 		break;
36163aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
36263aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
3639193e9c2SAndreas Jaekel 		break;
36463aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
36563aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
3669193e9c2SAndreas Jaekel 		break;
36763aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
36863aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
3699193e9c2SAndreas Jaekel 		break;
37063aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
37163aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
37263aba447SAndreas Jaekel 		break;
37363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
37463aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
37563aba447SAndreas Jaekel 		break;
37663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
37763aba447SAndreas Jaekel 		zev_print_znode_create(buf);
37863aba447SAndreas Jaekel 		break;
37963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
38063aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
38163aba447SAndreas Jaekel 		break;
38263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
38363aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
38463aba447SAndreas Jaekel 		break;
38563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
38663aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
38763aba447SAndreas Jaekel 		break;
38863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
38963aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
39063aba447SAndreas Jaekel 		break;
39163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
39263aba447SAndreas Jaekel 		zev_print_znode_link(buf);
39363aba447SAndreas Jaekel 		break;
39463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
39563aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
39663aba447SAndreas Jaekel 		break;
39763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
39863aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
39963aba447SAndreas Jaekel 		break;
40063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
40163aba447SAndreas Jaekel 		zev_print_znode_write(buf);
40263aba447SAndreas Jaekel 		break;
40363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
40463aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
40563aba447SAndreas Jaekel 		break;
40663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
40763aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
40863aba447SAndreas Jaekel 		break;
40963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
41063aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
4119193e9c2SAndreas Jaekel 		break;
4129193e9c2SAndreas Jaekel 	default:
41363aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
4149193e9c2SAndreas Jaekel 		exit(1);
4159193e9c2SAndreas Jaekel 	}
4169193e9c2SAndreas Jaekel }
4179193e9c2SAndreas Jaekel 
418e9a5e479SAndreas Jaekel static int
4194ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
4202bb8e5e2SAndreas Jaekel {
4212bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
4222bb8e5e2SAndreas Jaekel 	int ret;
4239193e9c2SAndreas Jaekel 	char buf[4096];
42468a46c64SAndreas Jaekel 	zev_event_t *ev;
42568a46c64SAndreas Jaekel 	int off = 0;
426e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
427e9a5e479SAndreas Jaekel 	int q_fd;
428e9a5e479SAndreas Jaekel 
4294ca7dd5eSAndreas Jaekel 	if (create_tmp_queue) {
430e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = 0;
431e9a5e479SAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
432e9a5e479SAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
433e9a5e479SAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
434e9a5e479SAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
435e9a5e479SAndreas Jaekel 
436e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
437e9a5e479SAndreas Jaekel 			perror("adding temporary queue failed");
438e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
439e9a5e479SAndreas Jaekel 		}
440e9a5e479SAndreas Jaekel 
4414ca7dd5eSAndreas Jaekel 		snprintf(buf, sizeof(buf),
4424ca7dd5eSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
443e9a5e479SAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
444e9a5e479SAndreas Jaekel 		if (q_fd < 0) {
445e9a5e479SAndreas Jaekel 			perror("opening queue device failed");
446e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
447e9a5e479SAndreas Jaekel 		}
4484ca7dd5eSAndreas Jaekel 	} else {
4494ca7dd5eSAndreas Jaekel 		q_fd = fd;
4504ca7dd5eSAndreas Jaekel 	}
451e9a5e479SAndreas Jaekel 
4522bb8e5e2SAndreas Jaekel 	while (1) {
453e9a5e479SAndreas Jaekel 		pfd[0].fd = q_fd;
4542bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
4552bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
4562bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4572bb8e5e2SAndreas Jaekel 			perror("poll failed");
4584ca7dd5eSAndreas Jaekel 			close(q_fd);
459e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4602bb8e5e2SAndreas Jaekel 		}
4612bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
4622bb8e5e2SAndreas Jaekel 			continue;
4632bb8e5e2SAndreas Jaekel 		/* data available */
464e9a5e479SAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
4652bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4662bb8e5e2SAndreas Jaekel 			perror("read failed");
4674ca7dd5eSAndreas Jaekel 			close(q_fd);
468e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4692bb8e5e2SAndreas Jaekel 		}
4702bb8e5e2SAndreas Jaekel 		if (ret == 0)
4712bb8e5e2SAndreas Jaekel 			continue;
47268a46c64SAndreas Jaekel 		while (ret > off) {
47368a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
47468a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
47568a46c64SAndreas Jaekel 			off += ev->header.record_len;
47668a46c64SAndreas Jaekel 		}
477108668daSAndreas Jaekel 		off = 0;
4782bb8e5e2SAndreas Jaekel 	}
4794ca7dd5eSAndreas Jaekel 	if (create_tmp_queue)
480e9a5e479SAndreas Jaekel 		close(q_fd);
481e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
4822bb8e5e2SAndreas Jaekel }
4832bb8e5e2SAndreas Jaekel 
4842bb8e5e2SAndreas Jaekel static void
4852bb8e5e2SAndreas Jaekel usage(char *progname)
4862bb8e5e2SAndreas Jaekel {
487e9a5e479SAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
488e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
489e9a5e479SAndreas Jaekel 	fprintf(stderr, " Status information:\n");
4902bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
4912bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
492e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
493e9a5e479SAndreas Jaekel 	        "information\n");
494e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
495e9a5e479SAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
496e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
497e9a5e479SAndreas Jaekel 	        "length\n");
498e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
499e9a5e479SAndreas Jaekel 	        "this pool\n");
5002bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
501e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
502e9a5e479SAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
503e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
5044ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
5054ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
506e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
507e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
508e9a5e479SAndreas Jaekel 	        "(default)\n");
509e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
510e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
5114ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
512e9a5e479SAndreas Jaekel 	        "length\n");
513e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
514e9a5e479SAndreas Jaekel 	        "throttle\n");
515e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
516e9a5e479SAndreas Jaekel 	fprintf(stderr, " Other options:\n");
517e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
518e9a5e479SAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
5194ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
5204ca7dd5eSAndreas Jaekel 		"queue name\n");
52101c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
522*5e286361SAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: addition output "
523*5e286361SAndreas Jaekel 	        "for some operations\n");
5242bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
5252bb8e5e2SAndreas Jaekel }
5262bb8e5e2SAndreas Jaekel 
5272bb8e5e2SAndreas Jaekel static int
5284ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
5292bb8e5e2SAndreas Jaekel {
530e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
531e9a5e479SAndreas Jaekel 	int namelen;
5322bb8e5e2SAndreas Jaekel 
533e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
534e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
535e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
5362bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5372bb8e5e2SAndreas Jaekel 	}
538e9a5e479SAndreas Jaekel 
539e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
540e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
5414ca7dd5eSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;
5424ca7dd5eSAndreas Jaekel 	if (blocking) {
5434ca7dd5eSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
5444ca7dd5eSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
5454ca7dd5eSAndreas Jaekel 	} else {
546e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
5474ca7dd5eSAndreas Jaekel 	}
548e9a5e479SAndreas Jaekel 
549e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
550e9a5e479SAndreas Jaekel 		perror("adding queue failed");
5512bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5522bb8e5e2SAndreas Jaekel 	}
5532bb8e5e2SAndreas Jaekel 	return (0);
5542bb8e5e2SAndreas Jaekel }
5552bb8e5e2SAndreas Jaekel 
5562bb8e5e2SAndreas Jaekel static int
557e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg)
558205a9bc9SAndreas Jaekel {
559e9a5e479SAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
560e9a5e479SAndreas Jaekel 	int namelen;
561205a9bc9SAndreas Jaekel 
562e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
563e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
564e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
565205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
566205a9bc9SAndreas Jaekel 	}
567e9a5e479SAndreas Jaekel 
5684ca7dd5eSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
5694ca7dd5eSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
570e9a5e479SAndreas Jaekel 
571e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
572e9a5e479SAndreas Jaekel 		perror("removing queue failed");
573e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
574e9a5e479SAndreas Jaekel 	}
575e9a5e479SAndreas Jaekel 	return (0);
576e9a5e479SAndreas Jaekel }
577e9a5e479SAndreas Jaekel 
578e9a5e479SAndreas Jaekel static int
579e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
580e9a5e479SAndreas Jaekel {
581e9a5e479SAndreas Jaekel 	uint64_t maxqueuelen;
582e9a5e479SAndreas Jaekel 
583e9a5e479SAndreas Jaekel 	errno = 0;
584e9a5e479SAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
585e9a5e479SAndreas Jaekel 	if (errno) {
586e9a5e479SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
587e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
588e9a5e479SAndreas Jaekel 	}
589e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
590e9a5e479SAndreas Jaekel 		perror("setting max queue length failed");
591205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
592205a9bc9SAndreas Jaekel 	}
593205a9bc9SAndreas Jaekel 	return (0);
594205a9bc9SAndreas Jaekel }
595205a9bc9SAndreas Jaekel 
596205a9bc9SAndreas Jaekel static int
5972bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
5982bb8e5e2SAndreas Jaekel {
5992bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
6002bb8e5e2SAndreas Jaekel 	int len;
6012bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
6022bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
6032bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
6042bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
6052bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
6062bb8e5e2SAndreas Jaekel 	}
6072bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
6082bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
6092bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
6102bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
6112bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
6122bb8e5e2SAndreas Jaekel 	}
6132bb8e5e2SAndreas Jaekel 	return (0);
6142bb8e5e2SAndreas Jaekel }
6152bb8e5e2SAndreas Jaekel 
6162bb8e5e2SAndreas Jaekel int
6172bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
6182bb8e5e2SAndreas Jaekel {
6192bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
6202bb8e5e2SAndreas Jaekel }
6212bb8e5e2SAndreas Jaekel 
6222bb8e5e2SAndreas Jaekel int
6232bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
6242bb8e5e2SAndreas Jaekel {
6252bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
6262bb8e5e2SAndreas Jaekel }
6272bb8e5e2SAndreas Jaekel 
62801c2c787SAndreas Jaekel static int
629e9a5e479SAndreas Jaekel zev_debug_info(int fd)
630e9a5e479SAndreas Jaekel {
631e9a5e479SAndreas Jaekel 	zev_ioctl_debug_info_t di;
632e9a5e479SAndreas Jaekel 
633e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
634e9a5e479SAndreas Jaekel 		perror("getting zev debug info failed");
635e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
636e9a5e479SAndreas Jaekel 	}
637e9a5e479SAndreas Jaekel 
638e9a5e479SAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
639*5e286361SAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
640*5e286361SAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
641*5e286361SAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
642e9a5e479SAndreas Jaekel 	return 0;
643e9a5e479SAndreas Jaekel }
644e9a5e479SAndreas Jaekel 
645e9a5e479SAndreas Jaekel static int
64601c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
64701c2c787SAndreas Jaekel {
64801c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
64901c2c787SAndreas Jaekel 	uint64_t guid;
65001c2c787SAndreas Jaekel 	int len;
65101c2c787SAndreas Jaekel 	char *p;
65201c2c787SAndreas Jaekel 
65301c2c787SAndreas Jaekel 	p = strchr(arg, ':');
65401c2c787SAndreas Jaekel 	if (!p) {
65501c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
65601c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
65701c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
65801c2c787SAndreas Jaekel 	}
65901c2c787SAndreas Jaekel 	*p = '\n';
66001c2c787SAndreas Jaekel 	p++;
66101c2c787SAndreas Jaekel 
66201c2c787SAndreas Jaekel 	errno = 0;
663e9a5e479SAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
66401c2c787SAndreas Jaekel 	if (errno) {
66501c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
66601c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
66701c2c787SAndreas Jaekel 	}
66801c2c787SAndreas Jaekel 
66901c2c787SAndreas Jaekel 	len = strlen(p);
67001c2c787SAndreas Jaekel 
67101c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
67201c2c787SAndreas Jaekel 	if (!mark) {
67301c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
67401c2c787SAndreas Jaekel 		        strerror(errno));
67501c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
67601c2c787SAndreas Jaekel 	}
67701c2c787SAndreas Jaekel 	mark->zev_guid = guid;
67801c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
67901c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
68001c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
68101c2c787SAndreas Jaekel 
68201c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
68301c2c787SAndreas Jaekel 		perror("queueing mark failed");
68401c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
68501c2c787SAndreas Jaekel 	}
68601c2c787SAndreas Jaekel 
68701c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
68801c2c787SAndreas Jaekel 	return (0);
68901c2c787SAndreas Jaekel }
69001c2c787SAndreas Jaekel 
691e9a5e479SAndreas Jaekel static int
692e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
693e9a5e479SAndreas Jaekel {
694e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
695e9a5e479SAndreas Jaekel 
6964ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
6974ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
698e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
699e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
700e9a5e479SAndreas Jaekel 	}
7014ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
702e9a5e479SAndreas Jaekel 
703e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
704e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
705e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
706e9a5e479SAndreas Jaekel 	}
707e9a5e479SAndreas Jaekel 	if (block) {
708e9a5e479SAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
709e9a5e479SAndreas Jaekel 	} else {
710e9a5e479SAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
711e9a5e479SAndreas Jaekel 	}
712e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
713e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
714e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
715e9a5e479SAndreas Jaekel 	}
716e9a5e479SAndreas Jaekel 	return (0);
717e9a5e479SAndreas Jaekel }
718e9a5e479SAndreas Jaekel 
719e9a5e479SAndreas Jaekel static int
720e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
721e9a5e479SAndreas Jaekel {
722e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
723e9a5e479SAndreas Jaekel 
724e9a5e479SAndreas Jaekel 	if (!len) {
725e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
726e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
727e9a5e479SAndreas Jaekel 	}
728e9a5e479SAndreas Jaekel 
7294ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
7304ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
731e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
732e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
733e9a5e479SAndreas Jaekel 	}
7344ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
735e9a5e479SAndreas Jaekel 
736e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
737e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
738e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
739e9a5e479SAndreas Jaekel 	}
740e9a5e479SAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
741e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
742e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
743e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
744e9a5e479SAndreas Jaekel 	}
745e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
746e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
747e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
748e9a5e479SAndreas Jaekel 	}
749e9a5e479SAndreas Jaekel 
750e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
751e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
752e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
753e9a5e479SAndreas Jaekel 	}
754e9a5e479SAndreas Jaekel 	return (0);
755e9a5e479SAndreas Jaekel }
756e9a5e479SAndreas Jaekel 
757e9a5e479SAndreas Jaekel static int
758e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
759e9a5e479SAndreas Jaekel {
760e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
761e9a5e479SAndreas Jaekel 
762e9a5e479SAndreas Jaekel 	if (!len) {
763e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
764e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
765e9a5e479SAndreas Jaekel 	}
766e9a5e479SAndreas Jaekel 
7674ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
7684ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
769e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
770e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
771e9a5e479SAndreas Jaekel 	}
7724ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
773e9a5e479SAndreas Jaekel 
774e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
775e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
776e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
777e9a5e479SAndreas Jaekel 	}
778e9a5e479SAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
779e9a5e479SAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
780e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
781e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
782e9a5e479SAndreas Jaekel 	}
7834ca7dd5eSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
784e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
785e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
786e9a5e479SAndreas Jaekel 	}
787e9a5e479SAndreas Jaekel 
788e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
789e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
790e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
791e9a5e479SAndreas Jaekel 	}
792e9a5e479SAndreas Jaekel 	return (0);
793e9a5e479SAndreas Jaekel }
794e9a5e479SAndreas Jaekel 
795e9a5e479SAndreas Jaekel static int
796e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg)
797e9a5e479SAndreas Jaekel {
798e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
799e9a5e479SAndreas Jaekel 
8004ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
8014ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
802e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
803e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
804e9a5e479SAndreas Jaekel 	}
8054ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
806e9a5e479SAndreas Jaekel 
807e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
808e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
809e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
810e9a5e479SAndreas Jaekel 	}
811e9a5e479SAndreas Jaekel 
812e9a5e479SAndreas Jaekel 	printf("queue        : %s\n", arg);
813e9a5e479SAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
814e9a5e479SAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
815e9a5e479SAndreas Jaekel 	printf("persistent   : %s\n",
816e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
817e9a5e479SAndreas Jaekel 	printf("blocking     : %s\n",
818e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
819e9a5e479SAndreas Jaekel 
820e9a5e479SAndreas Jaekel 	return (0);
821e9a5e479SAndreas Jaekel }
822e9a5e479SAndreas Jaekel 
823e9a5e479SAndreas Jaekel static int
824e9a5e479SAndreas Jaekel zev_list_queues(int fd)
825e9a5e479SAndreas Jaekel {
826e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
827e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
828e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
829e9a5e479SAndreas Jaekel 	uint64_t	i;
830e9a5e479SAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
831e9a5e479SAndreas Jaekel 
832e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
833e9a5e479SAndreas Jaekel 		perror("getting queue list failed");
834e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
835e9a5e479SAndreas Jaekel 	}
836e9a5e479SAndreas Jaekel 
837e9a5e479SAndreas Jaekel 	printf("Name                                     Size       "
838e9a5e479SAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
839e9a5e479SAndreas Jaekel 
840e9a5e479SAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
841e9a5e479SAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
842e9a5e479SAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
843e9a5e479SAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
844e9a5e479SAndreas Jaekel 
8454ca7dd5eSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
8464ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
8474ca7dd5eSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
8484ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
849e9a5e479SAndreas Jaekel 
850e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
851e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
852e9a5e479SAndreas Jaekel 				continue;
853e9a5e479SAndreas Jaekel 			perror("getting queue properties failed");
854e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
855e9a5e479SAndreas Jaekel 		}
856e9a5e479SAndreas Jaekel 
8574ca7dd5eSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
8584ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
8594ca7dd5eSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
8604ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
861e9a5e479SAndreas Jaekel 
862e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
863e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
864e9a5e479SAndreas Jaekel 				continue;
865e9a5e479SAndreas Jaekel 			perror("getting statistics data failed");
866e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
867e9a5e479SAndreas Jaekel 		}
868e9a5e479SAndreas Jaekel 
869e9a5e479SAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
870e9a5e479SAndreas Jaekel 		       " %-3s %-3s\n",
871e9a5e479SAndreas Jaekel 			name,
872e9a5e479SAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
873e9a5e479SAndreas Jaekel 			gqp.zev_max_queue_len,
874e9a5e479SAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
875e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
876e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
877e9a5e479SAndreas Jaekel 				 "yes" : "no");
878e9a5e479SAndreas Jaekel 	}
879e9a5e479SAndreas Jaekel 
880e9a5e479SAndreas Jaekel 	return (0);
881e9a5e479SAndreas Jaekel }
882e9a5e479SAndreas Jaekel 
8832bb8e5e2SAndreas Jaekel int
8842bb8e5e2SAndreas Jaekel main(int argc, char **argv)
8852bb8e5e2SAndreas Jaekel {
8862bb8e5e2SAndreas Jaekel 	int fd;
8872bb8e5e2SAndreas Jaekel 	int c;
8882bb8e5e2SAndreas Jaekel 	extern char *optarg;
8894ca7dd5eSAndreas Jaekel 	int create_tmp_queue = 1;
8904ca7dd5eSAndreas Jaekel 	char buf[MAXPATHLEN];
8912bb8e5e2SAndreas Jaekel 
8922bb8e5e2SAndreas Jaekel 	/* open device */
8932bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
8942bb8e5e2SAndreas Jaekel 	if (fd < 0) {
8952bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
8962bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
8972bb8e5e2SAndreas Jaekel 	}
8984ca7dd5eSAndreas Jaekel 	while ((c = getopt(argc, argv,
899*5e286361SAndreas Jaekel 	                   "vspd:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){
9002bb8e5e2SAndreas Jaekel 		switch(c) {
901*5e286361SAndreas Jaekel 		case 'v':
902*5e286361SAndreas Jaekel 			verbose++;
903*5e286361SAndreas Jaekel 			break;
9042bb8e5e2SAndreas Jaekel 		case 's':
905e9a5e479SAndreas Jaekel 			return zev_statistics(fd);
9062bb8e5e2SAndreas Jaekel 		case 'p':
9074ca7dd5eSAndreas Jaekel 			return zev_poll_events(fd, create_tmp_queue);
908e9a5e479SAndreas Jaekel 		case 'D':
909e9a5e479SAndreas Jaekel 			return zev_debug_info(fd);
9102bb8e5e2SAndreas Jaekel 		case 'd':
911e9a5e479SAndreas Jaekel 			close(fd);
9122bb8e5e2SAndreas Jaekel 			zev_device = optarg;
913e9a5e479SAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
914e9a5e479SAndreas Jaekel 			if (fd < 0) {
915e9a5e479SAndreas Jaekel 				perror("opening zev device failed");
916e9a5e479SAndreas Jaekel 				return EXIT_FAILURE;
917e9a5e479SAndreas Jaekel 			}
9184ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
9194ca7dd5eSAndreas Jaekel 			break;
9204ca7dd5eSAndreas Jaekel 		case 'q':
9214ca7dd5eSAndreas Jaekel 			snprintf(buf, sizeof(buf),
9224ca7dd5eSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
9234ca7dd5eSAndreas Jaekel 			close(fd);
9244ca7dd5eSAndreas Jaekel 			zev_device = buf;
9254ca7dd5eSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
9264ca7dd5eSAndreas Jaekel 			if (fd < 0) {
9274ca7dd5eSAndreas Jaekel 				perror("opening zev device failed");
9284ca7dd5eSAndreas Jaekel 				return EXIT_FAILURE;
9294ca7dd5eSAndreas Jaekel 			}
9304ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
9312bb8e5e2SAndreas Jaekel 			break;
932e9a5e479SAndreas Jaekel 		case 'l':
933e9a5e479SAndreas Jaekel 			return zev_list_queues(fd);
934e9a5e479SAndreas Jaekel 		case 'Q':
935e9a5e479SAndreas Jaekel 			return zev_set_global_max_queue_len(fd, optarg);
9364ca7dd5eSAndreas Jaekel 		case 'L':
937e9a5e479SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg, argv[optind]);
938205a9bc9SAndreas Jaekel 		case 't':
939e9a5e479SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg,
940e9a5e479SAndreas Jaekel 			                                     argv[optind]);
9412bb8e5e2SAndreas Jaekel 		case 'm':
9422bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
9432bb8e5e2SAndreas Jaekel 		case 'M':
9442bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
94501c2c787SAndreas Jaekel 		case 'k':
94601c2c787SAndreas Jaekel 			return zev_mark(fd, optarg);
947e9a5e479SAndreas Jaekel 		case 'a':
9484ca7dd5eSAndreas Jaekel 			return zev_add_queue(fd, optarg, 0);
9494ca7dd5eSAndreas Jaekel 		case 'A':
9504ca7dd5eSAndreas Jaekel 			return zev_add_queue(fd, optarg, 1);
951e9a5e479SAndreas Jaekel 		case 'r':
952e9a5e479SAndreas Jaekel 			return zev_remove_queue(fd, optarg);
953e9a5e479SAndreas Jaekel 		case 'b':
954e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 0);
955e9a5e479SAndreas Jaekel 		case 'B':
956e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 1);
957e9a5e479SAndreas Jaekel 		case 'P':
958e9a5e479SAndreas Jaekel 			return zev_queue_properties(fd, optarg);
9592bb8e5e2SAndreas Jaekel 		case 'h':
9602bb8e5e2SAndreas Jaekel 		case '?':
9612bb8e5e2SAndreas Jaekel 		default:
9622bb8e5e2SAndreas Jaekel 			usage(argv[0]);
9632bb8e5e2SAndreas Jaekel 		}
9642bb8e5e2SAndreas Jaekel 	}
9652bb8e5e2SAndreas Jaekel 	usage(argv[0]);
9662bb8e5e2SAndreas Jaekel 	close(fd);
967e9a5e479SAndreas Jaekel 	return EXIT_FAILURE;
9682bb8e5e2SAndreas Jaekel }
9692bb8e5e2SAndreas Jaekel 
970