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