xref: /titanic_53/usr/src/cmd/zevadm/zevadm.c (revision 205a9bc9923894a217a2d0059577e6956a93acba)
12bb8e5e2SAndreas Jaekel #include <stdio.h>
22bb8e5e2SAndreas Jaekel #include <unistd.h>
32bb8e5e2SAndreas Jaekel #include <stdlib.h>
42bb8e5e2SAndreas Jaekel #include <fcntl.h>
52bb8e5e2SAndreas Jaekel #include <stropts.h>
62bb8e5e2SAndreas Jaekel #include <poll.h>
72bb8e5e2SAndreas Jaekel #include <string.h>
82bb8e5e2SAndreas Jaekel #include <sys/fs/zev.h>
92bb8e5e2SAndreas Jaekel #include <errno.h>
102bb8e5e2SAndreas Jaekel 
112bb8e5e2SAndreas Jaekel #define OP_STATISTICS		(1 << 0)
122bb8e5e2SAndreas Jaekel #define OP_POLL_EVENTS		(1 << 1)
132bb8e5e2SAndreas Jaekel #define OP_MUTE_POOL		(1 << 2)
142bb8e5e2SAndreas Jaekel #define OP_UNMUTE_POOL		(1 << 3)
152bb8e5e2SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN	(1 << 4)
162bb8e5e2SAndreas Jaekel 
172bb8e5e2SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev"
182bb8e5e2SAndreas Jaekel 
192bb8e5e2SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
202bb8e5e2SAndreas Jaekel 
212bb8e5e2SAndreas Jaekel static void
222bb8e5e2SAndreas Jaekel zev_statistics(int fd)
232bb8e5e2SAndreas Jaekel {
242bb8e5e2SAndreas Jaekel 	zev_statistics_t zs;
252bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
262bb8e5e2SAndreas Jaekel 		perror("getting statistics data failed");
272bb8e5e2SAndreas Jaekel 		exit (EXIT_FAILURE);
282bb8e5e2SAndreas Jaekel 	}
292bb8e5e2SAndreas Jaekel 	printf("ZEV module state:\n");
302bb8e5e2SAndreas Jaekel 
312bb8e5e2SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
322bb8e5e2SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
33*205a9bc9SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
34*205a9bc9SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
352bb8e5e2SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
362bb8e5e2SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
372bb8e5e2SAndreas Jaekel 
382bb8e5e2SAndreas Jaekel 	printf("ZFS event statistics:\n");
392bb8e5e2SAndreas Jaekel 
402bb8e5e2SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
412bb8e5e2SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
422bb8e5e2SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
432bb8e5e2SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
442bb8e5e2SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
452bb8e5e2SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
462bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
472bb8e5e2SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
482bb8e5e2SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
492bb8e5e2SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
502bb8e5e2SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
512bb8e5e2SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
522bb8e5e2SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
532bb8e5e2SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
542bb8e5e2SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
552bb8e5e2SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
562bb8e5e2SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
572bb8e5e2SAndreas Jaekel }
582bb8e5e2SAndreas Jaekel 
592bb8e5e2SAndreas Jaekel static void
602bb8e5e2SAndreas Jaekel zev_poll_events(int fd)
612bb8e5e2SAndreas Jaekel {
622bb8e5e2SAndreas Jaekel 	struct pollfd pfd[1];
632bb8e5e2SAndreas Jaekel 	int ret;
642bb8e5e2SAndreas Jaekel 	char buf[1024];
652bb8e5e2SAndreas Jaekel 	while (1) {
662bb8e5e2SAndreas Jaekel 		pfd[0].fd = fd;
672bb8e5e2SAndreas Jaekel 		pfd[0].events = POLLIN;
682bb8e5e2SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
692bb8e5e2SAndreas Jaekel 		if (ret < 0) {
702bb8e5e2SAndreas Jaekel 			perror("poll failed");
712bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
722bb8e5e2SAndreas Jaekel 		}
732bb8e5e2SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
742bb8e5e2SAndreas Jaekel 			continue;
752bb8e5e2SAndreas Jaekel 		/* data available */
762bb8e5e2SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
772bb8e5e2SAndreas Jaekel 		if (ret < 0) {
782bb8e5e2SAndreas Jaekel 			perror("read failed");
792bb8e5e2SAndreas Jaekel 			exit(EXIT_FAILURE);
802bb8e5e2SAndreas Jaekel 		}
812bb8e5e2SAndreas Jaekel 		if (ret == 0)
822bb8e5e2SAndreas Jaekel 			continue;
832bb8e5e2SAndreas Jaekel 		write(fileno(stdout), buf, ret);
842bb8e5e2SAndreas Jaekel 	}
852bb8e5e2SAndreas Jaekel 	return;
862bb8e5e2SAndreas Jaekel }
872bb8e5e2SAndreas Jaekel 
882bb8e5e2SAndreas Jaekel static void
892bb8e5e2SAndreas Jaekel usage(char *progname)
902bb8e5e2SAndreas Jaekel {
912bb8e5e2SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
922bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
932bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
942bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
95*205a9bc9SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
962bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
972bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
982bb8e5e2SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
992bb8e5e2SAndreas Jaekel 	    ZEV_DEVICE);
1002bb8e5e2SAndreas Jaekel 	exit (EXIT_FAILURE);
1012bb8e5e2SAndreas Jaekel }
1022bb8e5e2SAndreas Jaekel 
1032bb8e5e2SAndreas Jaekel static int
1042bb8e5e2SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
1052bb8e5e2SAndreas Jaekel {
1062bb8e5e2SAndreas Jaekel 	uint64_t maxqueuelen;
1072bb8e5e2SAndreas Jaekel 
1082bb8e5e2SAndreas Jaekel 	errno = 0;
1092bb8e5e2SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
1102bb8e5e2SAndreas Jaekel 	if (errno) {
1112bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
1122bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
1132bb8e5e2SAndreas Jaekel 	}
1142bb8e5e2SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
1152bb8e5e2SAndreas Jaekel 		perror("setting max queue length failed");
1162bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
1172bb8e5e2SAndreas Jaekel 	}
1182bb8e5e2SAndreas Jaekel 	return (0);
1192bb8e5e2SAndreas Jaekel }
1202bb8e5e2SAndreas Jaekel 
1212bb8e5e2SAndreas Jaekel static int
122*205a9bc9SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
123*205a9bc9SAndreas Jaekel {
124*205a9bc9SAndreas Jaekel 	uint64_t queuelen;
125*205a9bc9SAndreas Jaekel 
126*205a9bc9SAndreas Jaekel 	errno = 0;
127*205a9bc9SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
128*205a9bc9SAndreas Jaekel 	if (errno) {
129*205a9bc9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
130*205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
131*205a9bc9SAndreas Jaekel 	}
132*205a9bc9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
133*205a9bc9SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
134*205a9bc9SAndreas Jaekel 		return (EXIT_FAILURE);
135*205a9bc9SAndreas Jaekel 	}
136*205a9bc9SAndreas Jaekel 	return (0);
137*205a9bc9SAndreas Jaekel }
138*205a9bc9SAndreas Jaekel 
139*205a9bc9SAndreas Jaekel static int
1402bb8e5e2SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
1412bb8e5e2SAndreas Jaekel {
1422bb8e5e2SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
1432bb8e5e2SAndreas Jaekel 	int len;
1442bb8e5e2SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
1452bb8e5e2SAndreas Jaekel 	len = strlen(poolname);
1462bb8e5e2SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
1472bb8e5e2SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
1482bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
1492bb8e5e2SAndreas Jaekel 	}
1502bb8e5e2SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
1512bb8e5e2SAndreas Jaekel 	pa.zev_poolname_len = len;
1522bb8e5e2SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
1532bb8e5e2SAndreas Jaekel 		perror("muting pool data failed");
1542bb8e5e2SAndreas Jaekel 		return (EXIT_FAILURE);
1552bb8e5e2SAndreas Jaekel 	}
1562bb8e5e2SAndreas Jaekel 	return (0);
1572bb8e5e2SAndreas Jaekel }
1582bb8e5e2SAndreas Jaekel 
1592bb8e5e2SAndreas Jaekel int
1602bb8e5e2SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
1612bb8e5e2SAndreas Jaekel {
1622bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
1632bb8e5e2SAndreas Jaekel }
1642bb8e5e2SAndreas Jaekel 
1652bb8e5e2SAndreas Jaekel int
1662bb8e5e2SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
1672bb8e5e2SAndreas Jaekel {
1682bb8e5e2SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
1692bb8e5e2SAndreas Jaekel }
1702bb8e5e2SAndreas Jaekel 
1712bb8e5e2SAndreas Jaekel int
1722bb8e5e2SAndreas Jaekel main(int argc, char **argv)
1732bb8e5e2SAndreas Jaekel {
1742bb8e5e2SAndreas Jaekel 	int fd;
1752bb8e5e2SAndreas Jaekel 	int c;
1762bb8e5e2SAndreas Jaekel 	int ops = 0;
1772bb8e5e2SAndreas Jaekel 	extern char *optarg;
1782bb8e5e2SAndreas Jaekel 
1792bb8e5e2SAndreas Jaekel 	/* open device */
1802bb8e5e2SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
1812bb8e5e2SAndreas Jaekel 	if (fd < 0) {
1822bb8e5e2SAndreas Jaekel 		perror("opening zev device failed");
1832bb8e5e2SAndreas Jaekel 		return EXIT_FAILURE;
1842bb8e5e2SAndreas Jaekel 	}
185*205a9bc9SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) {
1862bb8e5e2SAndreas Jaekel 		switch(c) {
1872bb8e5e2SAndreas Jaekel 		case 's':
1882bb8e5e2SAndreas Jaekel 			ops |= OP_STATISTICS;
1892bb8e5e2SAndreas Jaekel 			break;
1902bb8e5e2SAndreas Jaekel 		case 'p':
1912bb8e5e2SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
1922bb8e5e2SAndreas Jaekel 			break;
1932bb8e5e2SAndreas Jaekel 		case 'd':
1942bb8e5e2SAndreas Jaekel 			zev_device = optarg;
1952bb8e5e2SAndreas Jaekel 			break;
1962bb8e5e2SAndreas Jaekel 		case 'q':
1972bb8e5e2SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
198*205a9bc9SAndreas Jaekel 		case 't':
199*205a9bc9SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
2002bb8e5e2SAndreas Jaekel 		case 'm':
2012bb8e5e2SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
2022bb8e5e2SAndreas Jaekel 		case 'M':
2032bb8e5e2SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
2042bb8e5e2SAndreas Jaekel 		case 'h':
2052bb8e5e2SAndreas Jaekel 		case '?':
2062bb8e5e2SAndreas Jaekel 		default:
2072bb8e5e2SAndreas Jaekel 			usage(argv[0]);
2082bb8e5e2SAndreas Jaekel 		}
2092bb8e5e2SAndreas Jaekel 	}
2102bb8e5e2SAndreas Jaekel 	if (!ops)
2112bb8e5e2SAndreas Jaekel 		usage(argv[0]);
2122bb8e5e2SAndreas Jaekel 	if (ops & OP_STATISTICS)
2132bb8e5e2SAndreas Jaekel 		zev_statistics(fd);
2142bb8e5e2SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
2152bb8e5e2SAndreas Jaekel 		zev_poll_events(fd);
2162bb8e5e2SAndreas Jaekel 	close(fd);
2172bb8e5e2SAndreas Jaekel 	return EXIT_SUCCESS;
2182bb8e5e2SAndreas Jaekel }
2192bb8e5e2SAndreas Jaekel 
220