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