xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision fec460f8d37c03e6a5940c9a39765bc153ae8f78)
1a18c35b9SAndreas Jaekel #include <stdio.h>
2a18c35b9SAndreas Jaekel #include <unistd.h>
3a18c35b9SAndreas Jaekel #include <stdlib.h>
4a18c35b9SAndreas Jaekel #include <fcntl.h>
5a18c35b9SAndreas Jaekel #include <stropts.h>
6a18c35b9SAndreas Jaekel #include <poll.h>
7a18c35b9SAndreas Jaekel #include <string.h>
8a18c35b9SAndreas Jaekel #include <sys/fs/zev.h>
9a18c35b9SAndreas Jaekel #include <errno.h>
10a18c35b9SAndreas Jaekel 
11a18c35b9SAndreas Jaekel #define OP_STATISTICS		(1 << 0)
12a18c35b9SAndreas Jaekel #define OP_POLL_EVENTS		(1 << 1)
13a18c35b9SAndreas Jaekel #define OP_MUTE_POOL		(1 << 2)
14a18c35b9SAndreas Jaekel #define OP_UNMUTE_POOL		(1 << 3)
15a18c35b9SAndreas Jaekel #define OP_SET_MAX_QUEUE_LEN	(1 << 4)
16a18c35b9SAndreas Jaekel 
17a18c35b9SAndreas Jaekel #define ZEV_DEVICE "/devices/pseudo/zev@0:zev"
18a18c35b9SAndreas Jaekel 
19a18c35b9SAndreas Jaekel static char *zev_device = ZEV_DEVICE;
20a18c35b9SAndreas Jaekel 
21a18c35b9SAndreas Jaekel static void
22a18c35b9SAndreas Jaekel zev_statistics(int fd)
23a18c35b9SAndreas Jaekel {
24a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
25a18c35b9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
26a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
27a18c35b9SAndreas Jaekel 		exit (EXIT_FAILURE);
28a18c35b9SAndreas Jaekel 	}
29a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
30a18c35b9SAndreas Jaekel 
31a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
32a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
33*fec460f8SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
34*fec460f8SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
35a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
36a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
37a18c35b9SAndreas Jaekel 
38a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
39a18c35b9SAndreas Jaekel 
40a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
41a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
42a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
43a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
44a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
45a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
46a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
47a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
48a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
49a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
50a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
51a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
52a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
53a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
54a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
55a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
56a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
57a18c35b9SAndreas Jaekel }
58a18c35b9SAndreas Jaekel 
59a18c35b9SAndreas Jaekel static void
60a18c35b9SAndreas Jaekel zev_poll_events(int fd)
61a18c35b9SAndreas Jaekel {
62a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
63a18c35b9SAndreas Jaekel 	int ret;
64a18c35b9SAndreas Jaekel 	char buf[1024];
65a18c35b9SAndreas Jaekel 	while (1) {
66a18c35b9SAndreas Jaekel 		pfd[0].fd = fd;
67a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
68a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
69a18c35b9SAndreas Jaekel 		if (ret < 0) {
70a18c35b9SAndreas Jaekel 			perror("poll failed");
71a18c35b9SAndreas Jaekel 			exit(EXIT_FAILURE);
72a18c35b9SAndreas Jaekel 		}
73a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
74a18c35b9SAndreas Jaekel 			continue;
75a18c35b9SAndreas Jaekel 		/* data available */
76a18c35b9SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
77a18c35b9SAndreas Jaekel 		if (ret < 0) {
78a18c35b9SAndreas Jaekel 			perror("read failed");
79a18c35b9SAndreas Jaekel 			exit(EXIT_FAILURE);
80a18c35b9SAndreas Jaekel 		}
81a18c35b9SAndreas Jaekel 		if (ret == 0)
82a18c35b9SAndreas Jaekel 			continue;
83a18c35b9SAndreas Jaekel 		write(fileno(stdout), buf, ret);
84a18c35b9SAndreas Jaekel 	}
85a18c35b9SAndreas Jaekel 	return;
86a18c35b9SAndreas Jaekel }
87a18c35b9SAndreas Jaekel 
88a18c35b9SAndreas Jaekel static void
89a18c35b9SAndreas Jaekel usage(char *progname)
90a18c35b9SAndreas Jaekel {
91a18c35b9SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
92a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
93a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
94a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
95*fec460f8SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
96a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
97a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
98a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
99a18c35b9SAndreas Jaekel 	    ZEV_DEVICE);
100a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
101a18c35b9SAndreas Jaekel }
102a18c35b9SAndreas Jaekel 
103a18c35b9SAndreas Jaekel static int
104a18c35b9SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
105a18c35b9SAndreas Jaekel {
106a18c35b9SAndreas Jaekel 	uint64_t maxqueuelen;
107a18c35b9SAndreas Jaekel 
108a18c35b9SAndreas Jaekel 	errno = 0;
109a18c35b9SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
110a18c35b9SAndreas Jaekel 	if (errno) {
111a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
112a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
113a18c35b9SAndreas Jaekel 	}
114a18c35b9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
115a18c35b9SAndreas Jaekel 		perror("setting max queue length failed");
116a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
117a18c35b9SAndreas Jaekel 	}
118a18c35b9SAndreas Jaekel 	return (0);
119a18c35b9SAndreas Jaekel }
120a18c35b9SAndreas Jaekel 
121a18c35b9SAndreas Jaekel static int
122*fec460f8SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
123*fec460f8SAndreas Jaekel {
124*fec460f8SAndreas Jaekel 	uint64_t queuelen;
125*fec460f8SAndreas Jaekel 
126*fec460f8SAndreas Jaekel 	errno = 0;
127*fec460f8SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
128*fec460f8SAndreas Jaekel 	if (errno) {
129*fec460f8SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
130*fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
131*fec460f8SAndreas Jaekel 	}
132*fec460f8SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
133*fec460f8SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
134*fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
135*fec460f8SAndreas Jaekel 	}
136*fec460f8SAndreas Jaekel 	return (0);
137*fec460f8SAndreas Jaekel }
138*fec460f8SAndreas Jaekel 
139*fec460f8SAndreas Jaekel static int
140a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
141a18c35b9SAndreas Jaekel {
142a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
143a18c35b9SAndreas Jaekel 	int len;
144a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
145a18c35b9SAndreas Jaekel 	len = strlen(poolname);
146a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
147a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
148a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
149a18c35b9SAndreas Jaekel 	}
150a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
151a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
152a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
153a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
154a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
155a18c35b9SAndreas Jaekel 	}
156a18c35b9SAndreas Jaekel 	return (0);
157a18c35b9SAndreas Jaekel }
158a18c35b9SAndreas Jaekel 
159a18c35b9SAndreas Jaekel int
160a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
161a18c35b9SAndreas Jaekel {
162a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
163a18c35b9SAndreas Jaekel }
164a18c35b9SAndreas Jaekel 
165a18c35b9SAndreas Jaekel int
166a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
167a18c35b9SAndreas Jaekel {
168a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
169a18c35b9SAndreas Jaekel }
170a18c35b9SAndreas Jaekel 
171a18c35b9SAndreas Jaekel int
172a18c35b9SAndreas Jaekel main(int argc, char **argv)
173a18c35b9SAndreas Jaekel {
174a18c35b9SAndreas Jaekel 	int fd;
175a18c35b9SAndreas Jaekel 	int c;
176a18c35b9SAndreas Jaekel 	int ops = 0;
177a18c35b9SAndreas Jaekel 	extern char *optarg;
178a18c35b9SAndreas Jaekel 
179a18c35b9SAndreas Jaekel 	/* open device */
180a18c35b9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
181a18c35b9SAndreas Jaekel 	if (fd < 0) {
182a18c35b9SAndreas Jaekel 		perror("opening zev device failed");
183a18c35b9SAndreas Jaekel 		return EXIT_FAILURE;
184a18c35b9SAndreas Jaekel 	}
185*fec460f8SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) {
186a18c35b9SAndreas Jaekel 		switch(c) {
187a18c35b9SAndreas Jaekel 		case 's':
188a18c35b9SAndreas Jaekel 			ops |= OP_STATISTICS;
189a18c35b9SAndreas Jaekel 			break;
190a18c35b9SAndreas Jaekel 		case 'p':
191a18c35b9SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
192a18c35b9SAndreas Jaekel 			break;
193a18c35b9SAndreas Jaekel 		case 'd':
194a18c35b9SAndreas Jaekel 			zev_device = optarg;
195a18c35b9SAndreas Jaekel 			break;
196a18c35b9SAndreas Jaekel 		case 'q':
197a18c35b9SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
198*fec460f8SAndreas Jaekel 		case 't':
199*fec460f8SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
200a18c35b9SAndreas Jaekel 		case 'm':
201a18c35b9SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
202a18c35b9SAndreas Jaekel 		case 'M':
203a18c35b9SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
204a18c35b9SAndreas Jaekel 		case 'h':
205a18c35b9SAndreas Jaekel 		case '?':
206a18c35b9SAndreas Jaekel 		default:
207a18c35b9SAndreas Jaekel 			usage(argv[0]);
208a18c35b9SAndreas Jaekel 		}
209a18c35b9SAndreas Jaekel 	}
210a18c35b9SAndreas Jaekel 	if (!ops)
211a18c35b9SAndreas Jaekel 		usage(argv[0]);
212a18c35b9SAndreas Jaekel 	if (ops & OP_STATISTICS)
213a18c35b9SAndreas Jaekel 		zev_statistics(fd);
214a18c35b9SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
215a18c35b9SAndreas Jaekel 		zev_poll_events(fd);
216a18c35b9SAndreas Jaekel 	close(fd);
217a18c35b9SAndreas Jaekel 	return EXIT_SUCCESS;
218a18c35b9SAndreas Jaekel }
219a18c35b9SAndreas Jaekel 
220