xref: /titanic_52/usr/src/cmd/zevadm/zevadm.c (revision b9710123bf6fc26197428ae089042fb387a55032)
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>
10*b9710123SAndreas Jaekel #include <sys/sysmacros.h>
112bb8e5e2SAndreas Jaekel 
12e9a5e479SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:ctrl"
132bb8e5e2SAndreas Jaekel 
142bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
152bb8e5e2SAndreas Jaekel 
169193e9c2SAndreas Jaekel static char *zev_op_name[] = {
179193e9c2SAndreas Jaekel 	"ZEV_OP_ERROR",
1801c2c787SAndreas Jaekel 	"ZEV_OP_MARK",
199193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
209193e9c2SAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
219193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
229193e9c2SAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
239193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
249193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
259193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
269193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
279193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
289193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
299193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
309193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
319193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
329193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
339193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
349193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
359193e9c2SAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
369193e9c2SAndreas Jaekel 	NULL
379193e9c2SAndreas Jaekel };
389193e9c2SAndreas Jaekel 
395e286361SAndreas Jaekel static int verbose = 0;
405e286361SAndreas Jaekel 
41e9a5e479SAndreas Jaekel static int
422bb8e5e2SAndreas Jaekel zev_statistics(int fd)
432bb8e5e2SAndreas Jaekel {
442bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
45e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_GLOBAL_STATISTICS, &zs)) {
462bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
47e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
482bb8e5e2SAndreas Jaekel 	}
492bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
502bb8e5e2SAndreas Jaekel 
512bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
522bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
532bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
542bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
552bb8e5e2SAndreas Jaekel 
56e9a5e479SAndreas Jaekel 	printf("    discarded events        : %lu\n",
57e9a5e479SAndreas Jaekel 	    zs.zev_cnt_discarded_events);
58e9a5e479SAndreas Jaekel 	printf("    discarded bytes         : %lu\n\n", zs.zev_bytes_discarded);
59e9a5e479SAndreas Jaekel 
602bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
612bb8e5e2SAndreas Jaekel 
622bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
632bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
642bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
652bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
662bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
672bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
682bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
692bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
702bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
712bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
722bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
732bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
742bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
752bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
762bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
772bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
782bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
79e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
802bb8e5e2SAndreas Jaekel }
812bb8e5e2SAndreas Jaekel 
822bb8e5e2SAndreas Jaekel static void
8363aba447SAndreas Jaekel zev_print_error(char *buf)
8463aba447SAndreas Jaekel {
8563aba447SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
8663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
8763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
8863aba447SAndreas Jaekel 
8963aba447SAndreas Jaekel 	printf("%s %s: failed_op=%s msg=%s\n",
9063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
9163aba447SAndreas Jaekel 	       zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec));
9263aba447SAndreas Jaekel }
9363aba447SAndreas Jaekel 
9463aba447SAndreas Jaekel static void
9501c2c787SAndreas Jaekel zev_print_mark(char *buf)
9601c2c787SAndreas Jaekel {
9701c2c787SAndreas Jaekel 	zev_mark_t *rec = (zev_mark_t *)buf;
9801c2c787SAndreas Jaekel 	time_t op_time = rec->op_time;
9901c2c787SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
10001c2c787SAndreas Jaekel 
10101c2c787SAndreas Jaekel 	printf("%s %s: guid=%llu mark_id=%lld payload_len=%ld\n",
10201c2c787SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN], rec->guid, rec->mark_id,
10301c2c787SAndreas Jaekel 	       rec->payload_len);
10401c2c787SAndreas Jaekel }
10501c2c787SAndreas Jaekel 
10601c2c787SAndreas Jaekel static void
10763aba447SAndreas Jaekel zev_print_zfs_mount(char *buf)
10863aba447SAndreas Jaekel {
10963aba447SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
11063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
11163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
11263aba447SAndreas Jaekel 
11363aba447SAndreas Jaekel 	printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n",
11463aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
11563aba447SAndreas Jaekel 	       rec->guid,
11663aba447SAndreas Jaekel 	       rec->remount ? "true" : "false",
11763aba447SAndreas Jaekel 	       ZEV_DATASET(rec),
11863aba447SAndreas Jaekel 	       ZEV_MOUNTPOINT(rec));
11963aba447SAndreas Jaekel }
12063aba447SAndreas Jaekel 
12163aba447SAndreas Jaekel static void
12263aba447SAndreas Jaekel zev_print_zfs_umount(char *buf)
12363aba447SAndreas Jaekel {
12463aba447SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
12563aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
12663aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
12763aba447SAndreas Jaekel 
12863aba447SAndreas Jaekel 	printf("%s %s: guid=%llu\n",
12963aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
13063aba447SAndreas Jaekel 	       rec->guid);
13163aba447SAndreas Jaekel }
13263aba447SAndreas Jaekel 
13363aba447SAndreas Jaekel static void
13463aba447SAndreas Jaekel zev_print_zvol_truncate(char *buf)
13563aba447SAndreas Jaekel {
13663aba447SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
13763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
13863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
13963aba447SAndreas Jaekel 
14063aba447SAndreas Jaekel 	printf("%s %s: guid=%llu offset=%llu length=%llu\n",
14163aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
14263aba447SAndreas Jaekel 	       rec->guid,
14363aba447SAndreas Jaekel 	       rec->offset,
14463aba447SAndreas Jaekel 	       rec->length);
14563aba447SAndreas Jaekel }
14663aba447SAndreas Jaekel 
14763aba447SAndreas Jaekel static void
14863aba447SAndreas Jaekel zev_print_zvol_write(char *buf)
14963aba447SAndreas Jaekel {
15063aba447SAndreas Jaekel 	zev_print_zvol_truncate(buf);
15163aba447SAndreas Jaekel }
15263aba447SAndreas Jaekel 
15363aba447SAndreas Jaekel static void
15463aba447SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
15563aba447SAndreas Jaekel {
15663aba447SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
15763aba447SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
15863aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
15963aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
16063aba447SAndreas Jaekel 
16163aba447SAndreas Jaekel 	printf("%s %s: guid=%llu file=%llu.%llu\n",
16263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
16363aba447SAndreas Jaekel 	       rec->guid,
16463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
16563aba447SAndreas Jaekel }
16663aba447SAndreas Jaekel 
16763aba447SAndreas Jaekel static void
16863aba447SAndreas Jaekel zev_print_znode_create(char *buf)
16963aba447SAndreas Jaekel {
17063aba447SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
17163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
17263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
17363aba447SAndreas Jaekel 
174c035b1e8SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu "
175c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, parent.mtime=%llu, name='%s'\n",
17663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
17763aba447SAndreas Jaekel 	       rec->guid,
17863aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
17963aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
180c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->parent.mtime,
18163aba447SAndreas Jaekel 	       ZEV_NAME(rec));
18263aba447SAndreas Jaekel }
18363aba447SAndreas Jaekel 
18463aba447SAndreas Jaekel static void
18563aba447SAndreas Jaekel zev_print_znode_mkdir(char *buf)
18663aba447SAndreas Jaekel {
18763aba447SAndreas Jaekel 	zev_print_znode_create(buf);
18863aba447SAndreas Jaekel }
18963aba447SAndreas Jaekel 
19063aba447SAndreas Jaekel static void
19163aba447SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
19263aba447SAndreas Jaekel {
19363aba447SAndreas Jaekel 	zev_print_znode_create(buf);
19463aba447SAndreas Jaekel }
19563aba447SAndreas Jaekel 
19663aba447SAndreas Jaekel static void
19763aba447SAndreas Jaekel zev_print_znode_remove(char *buf)
19863aba447SAndreas Jaekel {
19963aba447SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
20063aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
20163aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
20263aba447SAndreas Jaekel 
2036db5d4ecSAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file.mtime=%llu name='%s'\n",
20463aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
20563aba447SAndreas Jaekel 	       rec->guid,
20663aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
2076db5d4ecSAndreas Jaekel 	       rec->file.mtime,
20863aba447SAndreas Jaekel 	       ZEV_NAME(rec));
20963aba447SAndreas Jaekel }
21063aba447SAndreas Jaekel 
21163aba447SAndreas Jaekel static void
21263aba447SAndreas Jaekel zev_print_znode_rmdir(char *buf)
21363aba447SAndreas Jaekel {
21463aba447SAndreas Jaekel 	zev_print_znode_remove(buf);
21563aba447SAndreas Jaekel }
21663aba447SAndreas Jaekel 
21763aba447SAndreas Jaekel static void
21863aba447SAndreas Jaekel zev_print_znode_link(char *buf)
21963aba447SAndreas Jaekel {
22063aba447SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
22163aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
22263aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
22363aba447SAndreas Jaekel 
22403101f54SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu "
22503101f54SAndreas Jaekel 	       "file.ctime=%llu parent.ctime=%llu name='%s'\n",
22663aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
22763aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
22863aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
22903101f54SAndreas Jaekel 	       rec->file.ctime, rec->parent.ctime,
23063aba447SAndreas Jaekel 	       ZEV_NAME(rec));
23163aba447SAndreas Jaekel 	printf("links: %d\n", rec->file.links);
23263aba447SAndreas Jaekel }
23363aba447SAndreas Jaekel 
23463aba447SAndreas Jaekel static void
23563aba447SAndreas Jaekel zev_print_znode_symlink(char *buf)
23663aba447SAndreas Jaekel {
23763aba447SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
23863aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
23963aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
24063aba447SAndreas Jaekel 
24163aba447SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n",
24263aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
24363aba447SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
24463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
24563aba447SAndreas Jaekel 	       ZEV_NAME(rec),
24663aba447SAndreas Jaekel 	       ZEV_LINK(rec));
24763aba447SAndreas Jaekel }
24863aba447SAndreas Jaekel 
24963aba447SAndreas Jaekel static void
25063aba447SAndreas Jaekel zev_print_znode_rename(char *buf)
25163aba447SAndreas Jaekel {
25263aba447SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
25363aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
25463aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
25563aba447SAndreas Jaekel 
25663aba447SAndreas Jaekel 	printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu "
257c035b1e8SAndreas Jaekel 	       "file.mtime=%llu, file.ctime=%llu, srcdir.mtime=%llu, "
258c035b1e8SAndreas Jaekel 	       "srcdir.ctime=%llu, dstdir.mtime=%llu, dstdir.ctime=%llu, "
25963aba447SAndreas Jaekel 	       "srcname='%s' dstname='%s'\n",
26063aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
26163aba447SAndreas Jaekel 	       rec->srcdir.ino, rec->srcdir.gen,
26263aba447SAndreas Jaekel 	       rec->dstdir.ino, rec->dstdir.gen,
26363aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
264c035b1e8SAndreas Jaekel 	       rec->file.mtime, rec->file.ctime,
265c035b1e8SAndreas Jaekel 	       rec->srcdir.mtime, rec->srcdir.ctime,
266c035b1e8SAndreas Jaekel 	       rec->dstdir.mtime, rec->dstdir.ctime,
26763aba447SAndreas Jaekel 	       ZEV_SRCNAME(rec),
26863aba447SAndreas Jaekel 	       ZEV_DSTNAME(rec));
26963aba447SAndreas Jaekel }
27063aba447SAndreas Jaekel 
27163aba447SAndreas Jaekel static void
2725e286361SAndreas Jaekel sig2hex_direct(const uint8_t *sig, char *hex)
2735e286361SAndreas Jaekel {
2745e286361SAndreas Jaekel 	int     i;
2755e286361SAndreas Jaekel 
2765e286361SAndreas Jaekel 	for (i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
2775e286361SAndreas Jaekel 		sprintf(hex + 2 * i, "%02x", sig[i]);
2785e286361SAndreas Jaekel 	}
2795e286361SAndreas Jaekel 	hex[SHA1_DIGEST_LENGTH * 2] = '\0';
2805e286361SAndreas Jaekel }
2815e286361SAndreas Jaekel 
2825e286361SAndreas Jaekel static void
28363aba447SAndreas Jaekel zev_print_znode_write(char *buf)
28463aba447SAndreas Jaekel {
28563aba447SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
28663aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
28763aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
2885e286361SAndreas Jaekel 	zev_sig_t *sig;
2895e286361SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
2905e286361SAndreas Jaekel 	int i;
29163aba447SAndreas Jaekel 
29263aba447SAndreas Jaekel 	printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
29363aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
29463aba447SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
29563aba447SAndreas Jaekel 	       rec->offset, rec->length);
2965e286361SAndreas Jaekel 	if (verbose) {
2975e286361SAndreas Jaekel 		for (i=0; i<rec->signature_cnt; i++) {
2985e286361SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(rec);
2995e286361SAndreas Jaekel 			sig += i;
3005e286361SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
3015e286361SAndreas Jaekel 			printf("  sig: level %d, offset %llu, value %s\n",
3025e286361SAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
3035e286361SAndreas Jaekel 		}
3045e286361SAndreas Jaekel 	}
30563aba447SAndreas Jaekel }
30663aba447SAndreas Jaekel 
30763aba447SAndreas Jaekel static void
30863aba447SAndreas Jaekel zev_print_znode_truncate(char *buf)
30963aba447SAndreas Jaekel {
31063aba447SAndreas Jaekel 	zev_print_znode_write(buf);
31163aba447SAndreas Jaekel }
31263aba447SAndreas Jaekel 
31363aba447SAndreas Jaekel static void
31463aba447SAndreas Jaekel zev_print_znode_setattr(char *buf)
31563aba447SAndreas Jaekel {
31663aba447SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
31763aba447SAndreas Jaekel 	time_t op_time = rec->op_time;
31863aba447SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
31963aba447SAndreas Jaekel 
320c035b1e8SAndreas Jaekel 	printf("%s %s: file=%llu.%llu mtime=%llu\n",
32163aba447SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
322c035b1e8SAndreas Jaekel 	       rec->file.ino, rec->file.gen, rec->file.mtime);
32363aba447SAndreas Jaekel }
32463aba447SAndreas Jaekel 
32563aba447SAndreas Jaekel static void
32663aba447SAndreas Jaekel zev_print_znode_acl(char *buf)
32763aba447SAndreas Jaekel {
32863aba447SAndreas Jaekel 	zev_print_znode_setattr(buf);
32963aba447SAndreas Jaekel }
33063aba447SAndreas Jaekel 
33163aba447SAndreas Jaekel static void
3329193e9c2SAndreas Jaekel zev_print_event(char *buf, int len)
3339193e9c2SAndreas Jaekel {
33463aba447SAndreas Jaekel 	int record_len;
33563aba447SAndreas Jaekel 	int op;
3369193e9c2SAndreas Jaekel 
33763aba447SAndreas Jaekel 	record_len = *(uint32_t *)buf;
33863aba447SAndreas Jaekel 	if (record_len != len) {
33963aba447SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
34063aba447SAndreas Jaekel 		        record_len, len);
3419193e9c2SAndreas Jaekel 		exit(1);
3429193e9c2SAndreas Jaekel 	}
34363aba447SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
3449193e9c2SAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
34563aba447SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
3469193e9c2SAndreas Jaekel 		exit(1);
3479193e9c2SAndreas Jaekel 	}
34863aba447SAndreas Jaekel 	switch (op) {
34963aba447SAndreas Jaekel 	case ZEV_OP_ERROR:
35063aba447SAndreas Jaekel 		zev_print_error(buf);
3519193e9c2SAndreas Jaekel 		break;
35201c2c787SAndreas Jaekel 	case ZEV_OP_MARK:
35301c2c787SAndreas Jaekel 		zev_print_mark(buf);
35401c2c787SAndreas Jaekel 		break;
35563aba447SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
35663aba447SAndreas Jaekel 		zev_print_zfs_mount(buf);
3579193e9c2SAndreas Jaekel 		break;
35863aba447SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
35963aba447SAndreas Jaekel 		zev_print_zfs_umount(buf);
3609193e9c2SAndreas Jaekel 		break;
36163aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
36263aba447SAndreas Jaekel 		zev_print_zvol_truncate(buf);
3639193e9c2SAndreas Jaekel 		break;
36463aba447SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
36563aba447SAndreas Jaekel 		zev_print_zvol_write(buf);
36663aba447SAndreas Jaekel 		break;
36763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
36863aba447SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
36963aba447SAndreas Jaekel 		break;
37063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
37163aba447SAndreas Jaekel 		zev_print_znode_create(buf);
37263aba447SAndreas Jaekel 		break;
37363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
37463aba447SAndreas Jaekel 		zev_print_znode_mkdir(buf);
37563aba447SAndreas Jaekel 		break;
37663aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
37763aba447SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
37863aba447SAndreas Jaekel 		break;
37963aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
38063aba447SAndreas Jaekel 		zev_print_znode_remove(buf);
38163aba447SAndreas Jaekel 		break;
38263aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
38363aba447SAndreas Jaekel 		zev_print_znode_rmdir(buf);
38463aba447SAndreas Jaekel 		break;
38563aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
38663aba447SAndreas Jaekel 		zev_print_znode_link(buf);
38763aba447SAndreas Jaekel 		break;
38863aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
38963aba447SAndreas Jaekel 		zev_print_znode_symlink(buf);
39063aba447SAndreas Jaekel 		break;
39163aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
39263aba447SAndreas Jaekel 		zev_print_znode_rename(buf);
39363aba447SAndreas Jaekel 		break;
39463aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
39563aba447SAndreas Jaekel 		zev_print_znode_write(buf);
39663aba447SAndreas Jaekel 		break;
39763aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
39863aba447SAndreas Jaekel 		zev_print_znode_truncate(buf);
39963aba447SAndreas Jaekel 		break;
40063aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
40163aba447SAndreas Jaekel 		zev_print_znode_setattr(buf);
40263aba447SAndreas Jaekel 		break;
40363aba447SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
40463aba447SAndreas Jaekel 		zev_print_znode_acl(buf);
4059193e9c2SAndreas Jaekel 		break;
4069193e9c2SAndreas Jaekel 	default:
40763aba447SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
4089193e9c2SAndreas Jaekel 		exit(1);
4099193e9c2SAndreas Jaekel 	}
4109193e9c2SAndreas Jaekel }
4119193e9c2SAndreas Jaekel 
412e9a5e479SAndreas Jaekel static int
4134ca7dd5eSAndreas Jaekel zev_poll_events(int fd, int create_tmp_queue)
4142bb8e5e2SAndreas Jaekel {
4152bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
4162bb8e5e2SAndreas Jaekel 	int ret;
4179193e9c2SAndreas Jaekel 	char buf[4096];
41868a46c64SAndreas Jaekel 	zev_event_t *ev;
41968a46c64SAndreas Jaekel 	int off = 0;
420e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
421e9a5e479SAndreas Jaekel 	int q_fd;
422e9a5e479SAndreas Jaekel 
4234ca7dd5eSAndreas Jaekel 	if (create_tmp_queue) {
424e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = 0;
425e9a5e479SAndreas Jaekel 		aq.zev_flags = ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
426e9a5e479SAndreas Jaekel 		snprintf(aq.zev_name, ZEV_MAX_QUEUE_NAME_LEN,
427e9a5e479SAndreas Jaekel 			 "zevadm.%ld.%ld", time(NULL), getpid());
428e9a5e479SAndreas Jaekel 		aq.zev_namelen = strlen(aq.zev_name);
429e9a5e479SAndreas Jaekel 
430e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
431e9a5e479SAndreas Jaekel 			perror("adding temporary queue failed");
432e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
433e9a5e479SAndreas Jaekel 		}
434e9a5e479SAndreas Jaekel 
4354ca7dd5eSAndreas Jaekel 		snprintf(buf, sizeof(buf),
4364ca7dd5eSAndreas Jaekel 		         "/devices/pseudo/zev@0:%s", aq.zev_name);
437e9a5e479SAndreas Jaekel 		q_fd = open(buf, O_RDONLY);
438e9a5e479SAndreas Jaekel 		if (q_fd < 0) {
439e9a5e479SAndreas Jaekel 			perror("opening queue device failed");
440e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
441e9a5e479SAndreas Jaekel 		}
4424ca7dd5eSAndreas Jaekel 	} else {
4434ca7dd5eSAndreas Jaekel 		q_fd = fd;
4444ca7dd5eSAndreas Jaekel 	}
445e9a5e479SAndreas Jaekel 
4462bb8e5e2SAndreas Jaekel 	while (1) {
447e9a5e479SAndreas Jaekel 		pfd[0].fd = q_fd;
4482bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
4492bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
4502bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4512bb8e5e2SAndreas Jaekel 			perror("poll failed");
4524ca7dd5eSAndreas Jaekel 			close(q_fd);
453e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4542bb8e5e2SAndreas Jaekel 		}
4552bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
4562bb8e5e2SAndreas Jaekel 			continue;
4572bb8e5e2SAndreas Jaekel 		/* data available */
458e9a5e479SAndreas Jaekel 		ret = read(q_fd, buf, sizeof(buf));
4592bb8e5e2SAndreas Jaekel 		if (ret < 0) {
4602bb8e5e2SAndreas Jaekel 			perror("read failed");
4614ca7dd5eSAndreas Jaekel 			close(q_fd);
462e9a5e479SAndreas Jaekel 			return(EXIT_FAILURE);
4632bb8e5e2SAndreas Jaekel 		}
4642bb8e5e2SAndreas Jaekel 		if (ret == 0)
4652bb8e5e2SAndreas Jaekel 			continue;
46668a46c64SAndreas Jaekel 		while (ret > off) {
46768a46c64SAndreas Jaekel 			ev = (zev_event_t *)(buf + off);
46868a46c64SAndreas Jaekel 			zev_print_event(buf + off, ev->header.record_len);
46968a46c64SAndreas Jaekel 			off += ev->header.record_len;
47068a46c64SAndreas Jaekel 		}
471108668daSAndreas Jaekel 		off = 0;
4722bb8e5e2SAndreas Jaekel 	}
4734ca7dd5eSAndreas Jaekel 	if (create_tmp_queue)
474e9a5e479SAndreas Jaekel 		close(q_fd);
475e9a5e479SAndreas Jaekel 	return EXIT_SUCCESS;
4762bb8e5e2SAndreas Jaekel }
4772bb8e5e2SAndreas Jaekel 
4782bb8e5e2SAndreas Jaekel static void
4792bb8e5e2SAndreas Jaekel usage(char *progname)
4802bb8e5e2SAndreas Jaekel {
481e9a5e479SAndreas Jaekel 	fprintf(stderr, "usage: %s [-d <dev>] [options]\n", progname);
482e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
483e9a5e479SAndreas Jaekel 	fprintf(stderr, " Status information:\n");
4842bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s                   show zev statistics\n");
4852bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p                   poll for ZFS events\n");
486e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -D                   print zev module debug "
487e9a5e479SAndreas Jaekel 	        "information\n");
488e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
489e9a5e479SAndreas Jaekel 	fprintf(stderr, " Tune zev module settings:\n");
490e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -Q <bytes>           set maximum event queue "
491e9a5e479SAndreas Jaekel 	        "length\n");
492e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -m <pool>            mute pool, no events for "
493e9a5e479SAndreas Jaekel 	        "this pool\n");
4942bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>            unmute pool\n");
495e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
496e9a5e479SAndreas Jaekel 	fprintf(stderr, " Queue management:\n");
497e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -l                   list queues\n");
4984ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -a <name>            add non-blocking queue\n");
4994ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -A <name>            add blocking queue\n");
500e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -r <name>            remove queue\n");
501e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -b <name>            make queue non-blocking "
502e9a5e479SAndreas Jaekel 	        "(default)\n");
503e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -B <name>            make queue block when full\n");
504e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -P <name>            display queue properties\n");
5054ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -L <name> <bytes>    set maximum event queue "
506e9a5e479SAndreas Jaekel 	        "length\n");
507e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -t <name> <bytes>    set queue length poll "
508e9a5e479SAndreas Jaekel 	        "throttle\n");
509e9a5e479SAndreas Jaekel 	fprintf(stderr, "\n");
510e9a5e479SAndreas Jaekel 	fprintf(stderr, " Other options:\n");
511e9a5e479SAndreas Jaekel 	fprintf(stderr, "   -d <dev>             non-default device file. "
512e9a5e479SAndreas Jaekel 	        "('%s')\n", ZEV_DEVICE);
5134ca7dd5eSAndreas Jaekel 	fprintf(stderr, "   -q <name>            use device file for this "
5144ca7dd5eSAndreas Jaekel 		"queue name\n");
51501c2c787SAndreas Jaekel 	fprintf(stderr, "   -k <guid>:<payload>  queue mark event\n");
516*b9710123SAndreas Jaekel 	fprintf(stderr, "   -c <filename>        list file's content "
517*b9710123SAndreas Jaekel 		"checksums\n");
5185e286361SAndreas Jaekel 	fprintf(stderr, "   -v                   verbose: addition output "
5195e286361SAndreas Jaekel 	        "for some operations\n");
5202bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
5212bb8e5e2SAndreas Jaekel }
5222bb8e5e2SAndreas Jaekel 
5232bb8e5e2SAndreas Jaekel static int
5244ca7dd5eSAndreas Jaekel zev_add_queue(int fd, char *arg, int blocking)
5252bb8e5e2SAndreas Jaekel {
526e9a5e479SAndreas Jaekel 	zev_ioctl_add_queue_t aq;
527e9a5e479SAndreas Jaekel 	int namelen;
5282bb8e5e2SAndreas Jaekel 
529e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
530e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
531e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
5322bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5332bb8e5e2SAndreas Jaekel 	}
534e9a5e479SAndreas Jaekel 
535e9a5e479SAndreas Jaekel 	aq.zev_namelen = namelen;
536e9a5e479SAndreas Jaekel 	strcpy(aq.zev_name, arg);
5374ca7dd5eSAndreas Jaekel 	aq.zev_flags = ZEV_FL_PERSISTENT;
5384ca7dd5eSAndreas Jaekel 	if (blocking) {
5394ca7dd5eSAndreas Jaekel 		aq.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
5404ca7dd5eSAndreas Jaekel 		aq.zev_max_queue_len = ZEV_MAX_QUEUE_LEN;
5414ca7dd5eSAndreas Jaekel 	} else {
542e9a5e479SAndreas Jaekel 		aq.zev_max_queue_len = (1024 * 1024);
5434ca7dd5eSAndreas Jaekel 	}
544e9a5e479SAndreas Jaekel 
545e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_ADD_QUEUE, &aq)) {
546e9a5e479SAndreas Jaekel 		perror("adding queue failed");
5472bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
5482bb8e5e2SAndreas Jaekel 	}
5492bb8e5e2SAndreas Jaekel 	return (0);
5502bb8e5e2SAndreas Jaekel }
5512bb8e5e2SAndreas Jaekel 
5522bb8e5e2SAndreas Jaekel static int
553e9a5e479SAndreas Jaekel zev_remove_queue(int fd, char *arg)
554205a9bc9SAndreas Jaekel {
555e9a5e479SAndreas Jaekel 	zev_ioctl_remove_queue_t aq;
556e9a5e479SAndreas Jaekel 	int namelen;
557205a9bc9SAndreas Jaekel 
558e9a5e479SAndreas Jaekel 	namelen = strlen(arg);
559e9a5e479SAndreas Jaekel 	if (namelen > ZEV_MAX_QUEUE_NAME_LEN) {
560e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long: %s\n", arg);
561205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
562205a9bc9SAndreas Jaekel 	}
563e9a5e479SAndreas Jaekel 
5644ca7dd5eSAndreas Jaekel 	aq.zev_queue_name.zev_namelen = namelen;
5654ca7dd5eSAndreas Jaekel 	strcpy(aq.zev_queue_name.zev_name, arg);
566e9a5e479SAndreas Jaekel 
567e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_REMOVE_QUEUE, &aq)) {
568e9a5e479SAndreas Jaekel 		perror("removing queue failed");
569e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
570e9a5e479SAndreas Jaekel 	}
571e9a5e479SAndreas Jaekel 	return (0);
572e9a5e479SAndreas Jaekel }
573e9a5e479SAndreas Jaekel 
574e9a5e479SAndreas Jaekel static int
575e9a5e479SAndreas Jaekel zev_set_global_max_queue_len(int fd, char *arg)
576e9a5e479SAndreas Jaekel {
577e9a5e479SAndreas Jaekel 	uint64_t maxqueuelen;
578e9a5e479SAndreas Jaekel 
579e9a5e479SAndreas Jaekel 	errno = 0;
580e9a5e479SAndreas Jaekel 	maxqueuelen = strtol(arg, (char **)NULL, 10);
581e9a5e479SAndreas Jaekel 	if (errno) {
582e9a5e479SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", arg);
583e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
584e9a5e479SAndreas Jaekel 	}
585e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
586e9a5e479SAndreas Jaekel 		perror("setting max queue length failed");
587205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
588205a9bc9SAndreas Jaekel 	}
589205a9bc9SAndreas Jaekel 	return (0);
590205a9bc9SAndreas Jaekel }
591205a9bc9SAndreas Jaekel 
592205a9bc9SAndreas Jaekel static int
5932bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
5942bb8e5e2SAndreas Jaekel {
5952bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
5962bb8e5e2SAndreas Jaekel 	int len;
5972bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
5982bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
5992bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
6002bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
6012bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
6022bb8e5e2SAndreas Jaekel 	}
6032bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
6042bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
6052bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
6062bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
6072bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
6082bb8e5e2SAndreas Jaekel 	}
6092bb8e5e2SAndreas Jaekel 	return (0);
6102bb8e5e2SAndreas Jaekel }
6112bb8e5e2SAndreas Jaekel 
6122bb8e5e2SAndreas Jaekel int
6132bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
6142bb8e5e2SAndreas Jaekel {
6152bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
6162bb8e5e2SAndreas Jaekel }
6172bb8e5e2SAndreas Jaekel 
6182bb8e5e2SAndreas Jaekel int
6192bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
6202bb8e5e2SAndreas Jaekel {
6212bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
6222bb8e5e2SAndreas Jaekel }
6232bb8e5e2SAndreas Jaekel 
62401c2c787SAndreas Jaekel static int
625e9a5e479SAndreas Jaekel zev_debug_info(int fd)
626e9a5e479SAndreas Jaekel {
627e9a5e479SAndreas Jaekel 	zev_ioctl_debug_info_t di;
628e9a5e479SAndreas Jaekel 
629e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_DEBUG_INFO, &di)) {
630e9a5e479SAndreas Jaekel 		perror("getting zev debug info failed");
631e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
632e9a5e479SAndreas Jaekel 	}
633e9a5e479SAndreas Jaekel 
634e9a5e479SAndreas Jaekel 	printf("memory allocated: %llu bytes\n", di.zev_memory_allocated);
6355e286361SAndreas Jaekel 	printf("checksum cache size: %llu\n", di.zev_chksum_cache_size);
6365e286361SAndreas Jaekel 	printf("checksum cache hits: %llu\n", di.zev_chksum_cache_hits);
6375e286361SAndreas Jaekel 	printf("checksum cache misses: %llu\n", di.zev_chksum_cache_misses);
638e9a5e479SAndreas Jaekel 	return 0;
639e9a5e479SAndreas Jaekel }
640e9a5e479SAndreas Jaekel 
641e9a5e479SAndreas Jaekel static int
64201c2c787SAndreas Jaekel zev_mark(int fd, char *arg)
64301c2c787SAndreas Jaekel {
64401c2c787SAndreas Jaekel 	zev_ioctl_mark_t *mark;
64501c2c787SAndreas Jaekel 	uint64_t guid;
64601c2c787SAndreas Jaekel 	int len;
64701c2c787SAndreas Jaekel 	char *p;
64801c2c787SAndreas Jaekel 
64901c2c787SAndreas Jaekel 	p = strchr(arg, ':');
65001c2c787SAndreas Jaekel 	if (!p) {
65101c2c787SAndreas Jaekel 		fprintf(stderr, "expected value is <guid>:<payload>, "
65201c2c787SAndreas Jaekel 		        "e.g. '123:hello'\n");
65301c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
65401c2c787SAndreas Jaekel 	}
65501c2c787SAndreas Jaekel 	*p = '\n';
65601c2c787SAndreas Jaekel 	p++;
65701c2c787SAndreas Jaekel 
65801c2c787SAndreas Jaekel 	errno = 0;
659e9a5e479SAndreas Jaekel 	guid = strtoll(arg, (char **)NULL, 10);
66001c2c787SAndreas Jaekel 	if (errno) {
66101c2c787SAndreas Jaekel 		fprintf(stderr, "guid must be a number.\n");
66201c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
66301c2c787SAndreas Jaekel 	}
66401c2c787SAndreas Jaekel 
66501c2c787SAndreas Jaekel 	len = strlen(p);
66601c2c787SAndreas Jaekel 
66701c2c787SAndreas Jaekel 	mark = malloc(sizeof(*mark) + len + 1);
66801c2c787SAndreas Jaekel 	if (!mark) {
66901c2c787SAndreas Jaekel 		fprintf(stderr, "can't allocate mark structure: %s\n",
67001c2c787SAndreas Jaekel 		        strerror(errno));
67101c2c787SAndreas Jaekel 		exit (EXIT_FAILURE);
67201c2c787SAndreas Jaekel 	}
67301c2c787SAndreas Jaekel 	mark->zev_guid = guid;
67401c2c787SAndreas Jaekel 	mark->zev_mark_id = 0;
67501c2c787SAndreas Jaekel 	mark->zev_payload_len = len;
67601c2c787SAndreas Jaekel 	strcpy(ZEV_PAYLOAD(mark), p);
67701c2c787SAndreas Jaekel 
67801c2c787SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_MARK, mark)) {
67901c2c787SAndreas Jaekel 		perror("queueing mark failed");
68001c2c787SAndreas Jaekel 		return (EXIT_FAILURE);
68101c2c787SAndreas Jaekel 	}
68201c2c787SAndreas Jaekel 
68301c2c787SAndreas Jaekel 	printf("mark id: %lu\n", mark->zev_mark_id);
68401c2c787SAndreas Jaekel 	return (0);
68501c2c787SAndreas Jaekel }
68601c2c787SAndreas Jaekel 
687e9a5e479SAndreas Jaekel static int
688e9a5e479SAndreas Jaekel zev_queue_blocking(int fd, char *arg, int block)
689e9a5e479SAndreas Jaekel {
690e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
691e9a5e479SAndreas Jaekel 
6924ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
6934ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
694e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
695e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
696e9a5e479SAndreas Jaekel 	}
6974ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
698e9a5e479SAndreas Jaekel 
699e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
700e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
701e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
702e9a5e479SAndreas Jaekel 	}
703e9a5e479SAndreas Jaekel 	if (block) {
704e9a5e479SAndreas Jaekel 		gqp.zev_flags |= ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
705e9a5e479SAndreas Jaekel 	} else {
706e9a5e479SAndreas Jaekel 		gqp.zev_flags &= ~ZEV_FL_BLOCK_WHILE_QUEUE_FULL;
707e9a5e479SAndreas Jaekel 	}
708e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
709e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
710e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
711e9a5e479SAndreas Jaekel 	}
712e9a5e479SAndreas Jaekel 	return (0);
713e9a5e479SAndreas Jaekel }
714e9a5e479SAndreas Jaekel 
715e9a5e479SAndreas Jaekel static int
716e9a5e479SAndreas Jaekel zev_set_max_queue_len(int fd, char *arg, char *len)
717e9a5e479SAndreas Jaekel {
718e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
719e9a5e479SAndreas Jaekel 
720e9a5e479SAndreas Jaekel 	if (!len) {
721e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter missing.\n");
722e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
723e9a5e479SAndreas Jaekel 	}
724e9a5e479SAndreas Jaekel 
7254ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
7264ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
727e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
728e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
729e9a5e479SAndreas Jaekel 	}
7304ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
731e9a5e479SAndreas Jaekel 
732e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
733e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
734e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
735e9a5e479SAndreas Jaekel 	}
736e9a5e479SAndreas Jaekel 	gqp.zev_max_queue_len = atol(len);
737e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len == 0 && strcmp("0", len)) {
738e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter garbled.\n");
739e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
740e9a5e479SAndreas Jaekel 	}
741e9a5e479SAndreas Jaekel 	if (gqp.zev_max_queue_len > ZEV_MAX_QUEUE_LEN) {
742e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue size parameter out of bounds.\n");
743e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
744e9a5e479SAndreas Jaekel 	}
745e9a5e479SAndreas Jaekel 
746e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
747e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
748e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
749e9a5e479SAndreas Jaekel 	}
750e9a5e479SAndreas Jaekel 	return (0);
751e9a5e479SAndreas Jaekel }
752e9a5e479SAndreas Jaekel 
753e9a5e479SAndreas Jaekel static int
754e9a5e479SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *arg, char *len)
755e9a5e479SAndreas Jaekel {
756e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
757e9a5e479SAndreas Jaekel 
758e9a5e479SAndreas Jaekel 	if (!len) {
759e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter missing.\n");
760e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
761e9a5e479SAndreas Jaekel 	}
762e9a5e479SAndreas Jaekel 
7634ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
7644ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
765e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
766e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
767e9a5e479SAndreas Jaekel 	}
7684ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
769e9a5e479SAndreas Jaekel 
770e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
771e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
772e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
773e9a5e479SAndreas Jaekel 	}
774e9a5e479SAndreas Jaekel 	gqp.zev_poll_wakeup_threshold = atol(len);
775e9a5e479SAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold == 0 && strcmp("0", len)) {
776e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter garbled.\n");
777e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
778e9a5e479SAndreas Jaekel 	}
7794ca7dd5eSAndreas Jaekel 	if (gqp.zev_poll_wakeup_threshold > ZEV_MAX_POLL_WAKEUP_QUEUE_LEN) {
780e9a5e479SAndreas Jaekel 		fprintf(stderr, "poll throttle parameter out of bounds.\n");
781e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
782e9a5e479SAndreas Jaekel 	}
783e9a5e479SAndreas Jaekel 
784e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_QUEUE_PROPERTIES, &gqp)) {
785e9a5e479SAndreas Jaekel 		perror("setting queue properties failed");
786e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
787e9a5e479SAndreas Jaekel 	}
788e9a5e479SAndreas Jaekel 	return (0);
789e9a5e479SAndreas Jaekel }
790e9a5e479SAndreas Jaekel 
791e9a5e479SAndreas Jaekel static int
792e9a5e479SAndreas Jaekel zev_queue_properties(int fd, char *arg)
793e9a5e479SAndreas Jaekel {
794e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
795e9a5e479SAndreas Jaekel 
7964ca7dd5eSAndreas Jaekel 	gqp.zev_queue_name.zev_namelen = strlen(arg);
7974ca7dd5eSAndreas Jaekel 	if (gqp.zev_queue_name.zev_namelen > ZEV_MAX_QUEUE_NAME_LEN) {
798e9a5e479SAndreas Jaekel 		fprintf(stderr, "queue name too long.\n");
799e9a5e479SAndreas Jaekel 		return EXIT_FAILURE;
800e9a5e479SAndreas Jaekel 	}
8014ca7dd5eSAndreas Jaekel 	strcpy(gqp.zev_queue_name.zev_name, arg);
802e9a5e479SAndreas Jaekel 
803e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
804e9a5e479SAndreas Jaekel 		perror("getting queue properties failed");
805e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
806e9a5e479SAndreas Jaekel 	}
807e9a5e479SAndreas Jaekel 
808e9a5e479SAndreas Jaekel 	printf("queue        : %s\n", arg);
809e9a5e479SAndreas Jaekel 	printf("max size     : %" PRIu64 "\n", gqp.zev_max_queue_len);
810e9a5e479SAndreas Jaekel 	printf("poll throttle: %" PRIu64 "\n", gqp.zev_poll_wakeup_threshold);
811e9a5e479SAndreas Jaekel 	printf("persistent   : %s\n",
812e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no");
813e9a5e479SAndreas Jaekel 	printf("blocking     : %s\n",
814e9a5e479SAndreas Jaekel 		gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ? "yes" : "no");
815e9a5e479SAndreas Jaekel 
816e9a5e479SAndreas Jaekel 	return (0);
817e9a5e479SAndreas Jaekel }
818e9a5e479SAndreas Jaekel 
819e9a5e479SAndreas Jaekel static int
820e9a5e479SAndreas Jaekel zev_list_queues(int fd)
821e9a5e479SAndreas Jaekel {
822e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_properties_t gqp;
823e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_list_t gql;
824e9a5e479SAndreas Jaekel 	zev_ioctl_get_queue_statistics_t gs;
825e9a5e479SAndreas Jaekel 	uint64_t	i;
826e9a5e479SAndreas Jaekel 	char		name[ZEV_MAX_QUEUE_NAME_LEN+1];
827e9a5e479SAndreas Jaekel 
828e9a5e479SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_QUEUE_LIST, &gql)) {
829e9a5e479SAndreas Jaekel 		perror("getting queue list failed");
830e9a5e479SAndreas Jaekel 		return (EXIT_FAILURE);
831e9a5e479SAndreas Jaekel 	}
832e9a5e479SAndreas Jaekel 
833e9a5e479SAndreas Jaekel 	printf("Name                                     Size       "
834e9a5e479SAndreas Jaekel 	       "Max Size   Wakeup Per Block\n");
835e9a5e479SAndreas Jaekel 
836e9a5e479SAndreas Jaekel 	for (i=0; i<gql.zev_n_queues; i++) {
837e9a5e479SAndreas Jaekel 		strncpy(name, gql.zev_queue_name[i].zev_name,
838e9a5e479SAndreas Jaekel 		        ZEV_MAX_QUEUE_NAME_LEN);
839e9a5e479SAndreas Jaekel 		name[gql.zev_queue_name[i].zev_namelen] = '\0';
840e9a5e479SAndreas Jaekel 
8414ca7dd5eSAndreas Jaekel 		memcpy(gqp.zev_queue_name.zev_name,
8424ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
8434ca7dd5eSAndreas Jaekel 		gqp.zev_queue_name.zev_namelen =
8444ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
845e9a5e479SAndreas Jaekel 
846e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_PROPERTIES, &gqp)) {
847e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
848e9a5e479SAndreas Jaekel 				continue;
849e9a5e479SAndreas Jaekel 			perror("getting queue properties failed");
850e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
851e9a5e479SAndreas Jaekel 		}
852e9a5e479SAndreas Jaekel 
8534ca7dd5eSAndreas Jaekel 		memcpy(gs.zev_queue_name.zev_name,
8544ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_name, ZEV_MAX_QUEUE_NAME_LEN);
8554ca7dd5eSAndreas Jaekel 		gs.zev_queue_name.zev_namelen =
8564ca7dd5eSAndreas Jaekel 		    gql.zev_queue_name[i].zev_namelen;
857e9a5e479SAndreas Jaekel 
858e9a5e479SAndreas Jaekel 		if (ioctl(fd, ZEV_IOC_GET_QUEUE_STATISTICS, &gs)) {
859e9a5e479SAndreas Jaekel 			if (errno == ENOENT)
860e9a5e479SAndreas Jaekel 				continue;
861e9a5e479SAndreas Jaekel 			perror("getting statistics data failed");
862e9a5e479SAndreas Jaekel 			return (EXIT_FAILURE);
863e9a5e479SAndreas Jaekel 		}
864e9a5e479SAndreas Jaekel 
865e9a5e479SAndreas Jaekel 		printf("%-40s %-10" PRIu64 " %-10" PRIu64 " %-6" PRIu64
866e9a5e479SAndreas Jaekel 		       " %-3s %-3s\n",
867e9a5e479SAndreas Jaekel 			name,
868e9a5e479SAndreas Jaekel 			gs.zev_statistics.zev_queue_len,
869e9a5e479SAndreas Jaekel 			gqp.zev_max_queue_len,
870e9a5e479SAndreas Jaekel 			gqp.zev_poll_wakeup_threshold,
871e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_PERSISTENT ? "yes" : "no",
872e9a5e479SAndreas Jaekel 			gqp.zev_flags & ZEV_FL_BLOCK_WHILE_QUEUE_FULL ?
873e9a5e479SAndreas Jaekel 				 "yes" : "no");
874e9a5e479SAndreas Jaekel 	}
875e9a5e479SAndreas Jaekel 
876e9a5e479SAndreas Jaekel 	return (0);
877e9a5e479SAndreas Jaekel }
878e9a5e479SAndreas Jaekel 
879*b9710123SAndreas Jaekel static int
880*b9710123SAndreas Jaekel zev_checksum(int dev_fd, char *filename)
881*b9710123SAndreas Jaekel {
882*b9710123SAndreas Jaekel 	int fd;
883*b9710123SAndreas Jaekel 	offset_t off;
884*b9710123SAndreas Jaekel 	offset_t data;
885*b9710123SAndreas Jaekel 	zev_sig_t *sig;
886*b9710123SAndreas Jaekel 	char *buf;
887*b9710123SAndreas Jaekel 	zev_ioctl_get_signatures_t *gs;
888*b9710123SAndreas Jaekel 	int i;
889*b9710123SAndreas Jaekel 	char sigval[(SHA1_DIGEST_LENGTH * 2) + 1];
890*b9710123SAndreas Jaekel 	int buf_size;
891*b9710123SAndreas Jaekel 
892*b9710123SAndreas Jaekel 	/* control struct, one lv1 signature and up to 256 lv0 signatures */
893*b9710123SAndreas Jaekel 	buf_size = (1 + 256) * sizeof(zev_sig_t);
894*b9710123SAndreas Jaekel 	buf = malloc(sizeof(zev_ioctl_get_signatures_t) + buf_size);
895*b9710123SAndreas Jaekel 	if (!buf) {
896*b9710123SAndreas Jaekel 		perror("can't allocate checksum buffer");
897*b9710123SAndreas Jaekel 		return (EXIT_FAILURE);
898*b9710123SAndreas Jaekel 	}
899*b9710123SAndreas Jaekel 
900*b9710123SAndreas Jaekel 	fd = open(filename, O_RDONLY);
901*b9710123SAndreas Jaekel 	if (fd < 0) {
902*b9710123SAndreas Jaekel 		perror("can't open file");
903*b9710123SAndreas Jaekel 		return (EXIT_FAILURE);
904*b9710123SAndreas Jaekel 	}
905*b9710123SAndreas Jaekel 
906*b9710123SAndreas Jaekel 	gs = (zev_ioctl_get_signatures_t *)buf;
907*b9710123SAndreas Jaekel 	gs->zev_fd = fd;
908*b9710123SAndreas Jaekel 	gs->zev_bufsize = buf_size;
909*b9710123SAndreas Jaekel 
910*b9710123SAndreas Jaekel 	off = 0;
911*b9710123SAndreas Jaekel 	data = 0;
912*b9710123SAndreas Jaekel 	while (1) {
913*b9710123SAndreas Jaekel 		errno = 0;
914*b9710123SAndreas Jaekel 		data = llseek(fd, off, SEEK_DATA);
915*b9710123SAndreas Jaekel 		if (data < 0) {
916*b9710123SAndreas Jaekel 			if (errno == ENXIO)	/* no more data */
917*b9710123SAndreas Jaekel 				break;
918*b9710123SAndreas Jaekel 			perror("llseek failed");
919*b9710123SAndreas Jaekel 			goto err;
920*b9710123SAndreas Jaekel 		}
921*b9710123SAndreas Jaekel 		data = P2ALIGN(data, ZEV_L1_SIZE);
922*b9710123SAndreas Jaekel 		off = data + ZEV_L1_SIZE;
923*b9710123SAndreas Jaekel 
924*b9710123SAndreas Jaekel 		gs->zev_offset = data;
925*b9710123SAndreas Jaekel 		gs->zev_len = ZEV_L1_SIZE;
926*b9710123SAndreas Jaekel 
927*b9710123SAndreas Jaekel 		if (ioctl(dev_fd, ZEV_IOC_GET_FILE_SIGNATURES, gs)) {
928*b9710123SAndreas Jaekel 			perror("ioctl to get signatures failed");
929*b9710123SAndreas Jaekel 			goto err;
930*b9710123SAndreas Jaekel 		}
931*b9710123SAndreas Jaekel 
932*b9710123SAndreas Jaekel 		for (i=0; i<gs->zev_signature_cnt; i++) {
933*b9710123SAndreas Jaekel 			sig = (zev_sig_t *)ZEV_SIGNATURES(gs);
934*b9710123SAndreas Jaekel 			sig += i;
935*b9710123SAndreas Jaekel 			sig2hex_direct(sig->value, sigval);
936*b9710123SAndreas Jaekel 			printf("level %d, offset %llu, value %s\n",
937*b9710123SAndreas Jaekel 			       sig->level, sig->block_offset, sigval);
938*b9710123SAndreas Jaekel 		}
939*b9710123SAndreas Jaekel 	}
940*b9710123SAndreas Jaekel 
941*b9710123SAndreas Jaekel 	free(buf);
942*b9710123SAndreas Jaekel 	close(fd);
943*b9710123SAndreas Jaekel 	return 0;
944*b9710123SAndreas Jaekel err:
945*b9710123SAndreas Jaekel 	free(buf);
946*b9710123SAndreas Jaekel 	close(fd);
947*b9710123SAndreas Jaekel 	return (EXIT_FAILURE);
948*b9710123SAndreas Jaekel }
949*b9710123SAndreas Jaekel 
9502bb8e5e2SAndreas Jaekel int
9512bb8e5e2SAndreas Jaekel main(int argc, char **argv)
9522bb8e5e2SAndreas Jaekel {
9532bb8e5e2SAndreas Jaekel 	int fd;
9542bb8e5e2SAndreas Jaekel 	int c;
9552bb8e5e2SAndreas Jaekel 	extern char *optarg;
9564ca7dd5eSAndreas Jaekel 	int create_tmp_queue = 1;
9574ca7dd5eSAndreas Jaekel 	char buf[MAXPATHLEN];
9582bb8e5e2SAndreas Jaekel 
9592bb8e5e2SAndreas Jaekel 	/* open device */
9602bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
9612bb8e5e2SAndreas Jaekel 	if (fd < 0) {
9622bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
9632bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
9642bb8e5e2SAndreas Jaekel 	}
9654ca7dd5eSAndreas Jaekel 	while ((c = getopt(argc, argv,
966*b9710123SAndreas Jaekel 	                   "vspc:d:Dlk:L:q:Qt:m:M:a:A:r:P:b:B:h?")) != -1){
9672bb8e5e2SAndreas Jaekel 		switch(c) {
9685e286361SAndreas Jaekel 		case 'v':
9695e286361SAndreas Jaekel 			verbose++;
9705e286361SAndreas Jaekel 			break;
9712bb8e5e2SAndreas Jaekel 		case 's':
972e9a5e479SAndreas Jaekel 			return zev_statistics(fd);
9732bb8e5e2SAndreas Jaekel 		case 'p':
9744ca7dd5eSAndreas Jaekel 			return zev_poll_events(fd, create_tmp_queue);
975*b9710123SAndreas Jaekel 		case 'c':
976*b9710123SAndreas Jaekel 			return zev_checksum(fd, optarg);
977e9a5e479SAndreas Jaekel 		case 'D':
978e9a5e479SAndreas Jaekel 			return zev_debug_info(fd);
9792bb8e5e2SAndreas Jaekel 		case 'd':
980e9a5e479SAndreas Jaekel 			close(fd);
9812bb8e5e2SAndreas Jaekel 			zev_device = optarg;
982e9a5e479SAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
983e9a5e479SAndreas Jaekel 			if (fd < 0) {
984e9a5e479SAndreas Jaekel 				perror("opening zev device failed");
985e9a5e479SAndreas Jaekel 				return EXIT_FAILURE;
986e9a5e479SAndreas Jaekel 			}
9874ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
9884ca7dd5eSAndreas Jaekel 			break;
9894ca7dd5eSAndreas Jaekel 		case 'q':
9904ca7dd5eSAndreas Jaekel 			snprintf(buf, sizeof(buf),
9914ca7dd5eSAndreas Jaekel 				 "/devices/pseudo/zev@0:%s", optarg);
9924ca7dd5eSAndreas Jaekel 			close(fd);
9934ca7dd5eSAndreas Jaekel 			zev_device = buf;
9944ca7dd5eSAndreas Jaekel 			fd = open(zev_device, O_RDONLY);
9954ca7dd5eSAndreas Jaekel 			if (fd < 0) {
9964ca7dd5eSAndreas Jaekel 				perror("opening zev device failed");
9974ca7dd5eSAndreas Jaekel 				return EXIT_FAILURE;
9984ca7dd5eSAndreas Jaekel 			}
9994ca7dd5eSAndreas Jaekel 			create_tmp_queue = 0;
10002bb8e5e2SAndreas Jaekel 			break;
1001e9a5e479SAndreas Jaekel 		case 'l':
1002e9a5e479SAndreas Jaekel 			return zev_list_queues(fd);
1003e9a5e479SAndreas Jaekel 		case 'Q':
1004e9a5e479SAndreas Jaekel 			return zev_set_global_max_queue_len(fd, optarg);
10054ca7dd5eSAndreas Jaekel 		case 'L':
1006e9a5e479SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg, argv[optind]);
1007205a9bc9SAndreas Jaekel 		case 't':
1008e9a5e479SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg,
1009e9a5e479SAndreas Jaekel 			                                     argv[optind]);
10102bb8e5e2SAndreas Jaekel 		case 'm':
10112bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
10122bb8e5e2SAndreas Jaekel 		case 'M':
10132bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
101401c2c787SAndreas Jaekel 		case 'k':
101501c2c787SAndreas Jaekel 			return zev_mark(fd, optarg);
1016e9a5e479SAndreas Jaekel 		case 'a':
10174ca7dd5eSAndreas Jaekel 			return zev_add_queue(fd, optarg, 0);
10184ca7dd5eSAndreas Jaekel 		case 'A':
10194ca7dd5eSAndreas Jaekel 			return zev_add_queue(fd, optarg, 1);
1020e9a5e479SAndreas Jaekel 		case 'r':
1021e9a5e479SAndreas Jaekel 			return zev_remove_queue(fd, optarg);
1022e9a5e479SAndreas Jaekel 		case 'b':
1023e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 0);
1024e9a5e479SAndreas Jaekel 		case 'B':
1025e9a5e479SAndreas Jaekel 			return zev_queue_blocking(fd, optarg, 1);
1026e9a5e479SAndreas Jaekel 		case 'P':
1027e9a5e479SAndreas Jaekel 			return zev_queue_properties(fd, optarg);
10282bb8e5e2SAndreas Jaekel 		case 'h':
10292bb8e5e2SAndreas Jaekel 		case '?':
10302bb8e5e2SAndreas Jaekel 		default:
10312bb8e5e2SAndreas Jaekel 			usage(argv[0]);
10322bb8e5e2SAndreas Jaekel 		}
10332bb8e5e2SAndreas Jaekel 	}
10342bb8e5e2SAndreas Jaekel 	usage(argv[0]);
10352bb8e5e2SAndreas Jaekel 	close(fd);
1036e9a5e479SAndreas Jaekel 	return EXIT_FAILURE;
10372bb8e5e2SAndreas Jaekel }
10382bb8e5e2SAndreas Jaekel 
1039