xref: /titanic_51/usr/src/cmd/zevadm/zevadm.c (revision 2bb8e5e2ef829a38e0408e7207b4aa15f5eb947b)
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("    bytes read from device  : %lu\n", zs.zev_bytes_read);
34 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
35 
36 	printf("ZFS event statistics:\n");
37 
38 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
39 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
40 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
41 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
42 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
43 	printf("    ZNODE close after update: %lu\n",
44 	    zs.zev_cnt_znode_close_after_update);
45 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
46 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
47 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
48 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
49 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
50 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
51 	printf("    ZNODE truncate          : %lu\n",
52 	    zs.zev_cnt_znode_truncate);
53 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
54 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
55 }
56 
57 static void
58 zev_poll_events(int fd)
59 {
60 	struct pollfd pfd[1];
61 	int ret;
62 	char buf[1024];
63 	while (1) {
64 		pfd[0].fd = fd;
65 		pfd[0].events = POLLIN;
66 		ret = poll(pfd, 1, 1000);
67 		if (ret < 0) {
68 			perror("poll failed");
69 			exit(EXIT_FAILURE);
70 		}
71 		if (!(pfd[0].revents & POLLIN))
72 			continue;
73 		/* data available */
74 		ret = read(fd, buf, sizeof(buf));
75 		if (ret < 0) {
76 			perror("read failed");
77 			exit(EXIT_FAILURE);
78 		}
79 		if (ret == 0)
80 			continue;
81 		write(fileno(stdout), buf, ret);
82 	}
83 	return;
84 }
85 
86 static void
87 usage(char *progname)
88 {
89 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
90 	fprintf(stderr, "   -s         show zev statistics\n");
91 	fprintf(stderr, "   -p         poll for ZFS events\n");
92 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
93 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
94 	fprintf(stderr, "   -M <pool>  unmute pool\n");
95 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
96 	    ZEV_DEVICE);
97 	exit (EXIT_FAILURE);
98 }
99 
100 static int
101 zev_set_max_queue_len(int fd, char *optarg)
102 {
103 	uint64_t maxqueuelen;
104 
105 	errno = 0;
106 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
107 	if (errno) {
108 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
109 		return (EXIT_FAILURE);
110 	}
111 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
112 		perror("setting max queue length failed");
113 		return (EXIT_FAILURE);
114 	}
115 	return (0);
116 }
117 
118 static int
119 zev_mute_unmute_impl(int fd, char *poolname, int mute)
120 {
121 	zev_ioctl_poolarg_t pa;
122 	int len;
123 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
124 	len = strlen(poolname);
125 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
126 		fprintf(stderr, "invalid poolname: %s\n", poolname);
127 		return (EXIT_FAILURE);
128 	}
129 	strcpy(pa.zev_poolname, poolname);
130 	pa.zev_poolname_len = len;
131 	if (ioctl(fd, op, &pa)) {
132 		perror("muting pool data failed");
133 		return (EXIT_FAILURE);
134 	}
135 	return (0);
136 }
137 
138 int
139 zev_mute_pool(int fd, char *poolname)
140 {
141 	return zev_mute_unmute_impl(fd, poolname, 1);
142 }
143 
144 int
145 zev_unmute_pool(int fd, char *poolname)
146 {
147 	return zev_mute_unmute_impl(fd, poolname, 0);
148 }
149 
150 int
151 main(int argc, char **argv)
152 {
153 	int fd;
154 	int c;
155 	int ops = 0;
156 	extern char *optarg;
157 
158 	/* open device */
159 	fd = open(zev_device, O_RDONLY);
160 	if (fd < 0) {
161 		perror("opening zev device failed");
162 		return EXIT_FAILURE;
163 	}
164 	while ((c = getopt(argc, argv, "spdq:m:M:h?")) != -1) {
165 		switch(c) {
166 		case 's':
167 			ops |= OP_STATISTICS;
168 			break;
169 		case 'p':
170 			ops |= OP_POLL_EVENTS;
171 			break;
172 		case 'd':
173 			zev_device = optarg;
174 			break;
175 		case 'q':
176 			return zev_set_max_queue_len(fd, optarg);
177 		case 'm':
178 			return zev_mute_pool(fd, optarg);
179 		case 'M':
180 			return zev_unmute_pool(fd, optarg);
181 		case 'h':
182 		case '?':
183 		default:
184 			usage(argv[0]);
185 		}
186 	}
187 	if (!ops)
188 		usage(argv[0]);
189 	if (ops & OP_STATISTICS)
190 		zev_statistics(fd);
191 	if (ops & OP_POLL_EVENTS)
192 		zev_poll_events(fd);
193 	close(fd);
194 	return EXIT_SUCCESS;
195 }
196 
197