xref: /titanic_44/usr/src/cmd/zevadm/zevadm.c (revision f2dd45e53f90c129616b7542527d78a7cedadbc8)
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 
21aafc540fSAndreas Jaekel static char *zev_op_name[] = {
22aafc540fSAndreas Jaekel 	"ZEV_OP_ERROR",
23aafc540fSAndreas Jaekel 	"ZEV_OP_ZFS_MOUNT",
24aafc540fSAndreas Jaekel 	"ZEV_OP_ZFS_UMOUNT",
25aafc540fSAndreas Jaekel 	"ZEV_OP_ZVOL_WRITE",
26aafc540fSAndreas Jaekel 	"ZEV_OP_ZVOL_TRUNCATE",
27aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE",
28aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_CREATE",
29aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_MKDIR",
30aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_MAKE_XATTR_DIR",
31aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_REMOVE",
32aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_RMDIR",
33aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_LINK",
34aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_SYMLINK",
35aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_RENAME",
36aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_WRITE",
37aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_TRUNCATE",
38aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_SETATTR",
39aafc540fSAndreas Jaekel 	"ZEV_OP_ZNODE_ACL",
40aafc540fSAndreas Jaekel 	NULL
41aafc540fSAndreas Jaekel };
42aafc540fSAndreas Jaekel 
43a18c35b9SAndreas Jaekel static void
44a18c35b9SAndreas Jaekel zev_statistics(int fd)
45a18c35b9SAndreas Jaekel {
46a18c35b9SAndreas Jaekel 	zev_statistics_t zs;
47a18c35b9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_GET_STATISTICS, &zs)) {
48a18c35b9SAndreas Jaekel 		perror("getting statistics data failed");
49a18c35b9SAndreas Jaekel 		exit (EXIT_FAILURE);
50a18c35b9SAndreas Jaekel 	}
51a18c35b9SAndreas Jaekel 	printf("ZEV module state:\n");
52a18c35b9SAndreas Jaekel 
53a18c35b9SAndreas Jaekel 	printf("    queue length in bytes   : %lu\n", zs.zev_queue_len);
54a18c35b9SAndreas Jaekel 	printf("    queue length limit      : %lu\n", zs.zev_max_queue_len);
55fec460f8SAndreas Jaekel 	printf("    poll wakeup throttle    : %lu\n\n",
56fec460f8SAndreas Jaekel 	    zs.zev_poll_wakeup_queue_len);
57a18c35b9SAndreas Jaekel 	printf("    bytes read from device  : %lu\n", zs.zev_bytes_read);
58a18c35b9SAndreas Jaekel 	printf("    module internal errors  : %lu\n\n", zs.zev_cnt_errors);
59a18c35b9SAndreas Jaekel 
60a18c35b9SAndreas Jaekel 	printf("ZFS event statistics:\n");
61a18c35b9SAndreas Jaekel 
62a18c35b9SAndreas Jaekel 	printf("    total ZFS events        : %lu\n", zs.zev_cnt_total_events);
63a18c35b9SAndreas Jaekel 	printf("    ZFS mount               : %lu\n", zs.zev_cnt_zfs_mount);
64a18c35b9SAndreas Jaekel 	printf("    ZFS umount              : %lu\n", zs.zev_cnt_zfs_umount);
65a18c35b9SAndreas Jaekel 	printf("    ZVOL write              : %lu\n", zs.zev_cnt_zvol_write);
66a18c35b9SAndreas Jaekel 	printf("    ZVOL truncate           : %lu\n", zs.zev_cnt_zvol_truncate);
67a18c35b9SAndreas Jaekel 	printf("    ZNODE close after update: %lu\n",
68a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_close_after_update);
69a18c35b9SAndreas Jaekel 	printf("    ZNODE create            : %lu\n", zs.zev_cnt_znode_create);
70a18c35b9SAndreas Jaekel 	printf("    ZNODE remove            : %lu\n", zs.zev_cnt_znode_remove);
71a18c35b9SAndreas Jaekel 	printf("    ZNODE link              : %lu\n", zs.zev_cnt_znode_link);
72a18c35b9SAndreas Jaekel 	printf("    ZNODE symlink           : %lu\n", zs.zev_cnt_znode_symlink);
73a18c35b9SAndreas Jaekel 	printf("    ZNODE rename            : %lu\n", zs.zev_cnt_znode_rename);
74a18c35b9SAndreas Jaekel 	printf("    ZNODE write             : %lu\n", zs.zev_cnt_znode_write);
75a18c35b9SAndreas Jaekel 	printf("    ZNODE truncate          : %lu\n",
76a18c35b9SAndreas Jaekel 	    zs.zev_cnt_znode_truncate);
77a18c35b9SAndreas Jaekel 	printf("    ZNODE setattr           : %lu\n", zs.zev_cnt_znode_setattr);
78a18c35b9SAndreas Jaekel 	printf("    ZNODE acl               : %lu\n", zs.zev_cnt_znode_acl);
79a18c35b9SAndreas Jaekel }
80a18c35b9SAndreas Jaekel 
81a18c35b9SAndreas Jaekel static void
82*f2dd45e5SAndreas Jaekel zev_print_error(char *buf)
83*f2dd45e5SAndreas Jaekel {
84*f2dd45e5SAndreas Jaekel 	zev_error_t *rec = (zev_error_t *)buf;
85*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
86*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
87*f2dd45e5SAndreas Jaekel 
88*f2dd45e5SAndreas Jaekel 	printf("%s %s: failed_op=%s msg=%s\n",
89*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
90*f2dd45e5SAndreas Jaekel 	       zev_op_name[rec->failed_op - ZEV_OP_MIN], ZEV_ERRSTR(rec));
91*f2dd45e5SAndreas Jaekel }
92*f2dd45e5SAndreas Jaekel 
93*f2dd45e5SAndreas Jaekel static void
94*f2dd45e5SAndreas Jaekel zev_print_zfs_mount(char *buf)
95*f2dd45e5SAndreas Jaekel {
96*f2dd45e5SAndreas Jaekel 	zev_zfs_mount_t *rec = (zev_zfs_mount_t *)buf;
97*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
98*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
99*f2dd45e5SAndreas Jaekel 
100*f2dd45e5SAndreas Jaekel 	printf("%s %s: guid=%llu remount=%s dataset='%s' mountpoint='%s'\n",
101*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
102*f2dd45e5SAndreas Jaekel 	       rec->guid,
103*f2dd45e5SAndreas Jaekel 	       rec->remount ? "true" : "false",
104*f2dd45e5SAndreas Jaekel 	       ZEV_DATASET(rec),
105*f2dd45e5SAndreas Jaekel 	       ZEV_MOUNTPOINT(rec));
106*f2dd45e5SAndreas Jaekel }
107*f2dd45e5SAndreas Jaekel 
108*f2dd45e5SAndreas Jaekel static void
109*f2dd45e5SAndreas Jaekel zev_print_zfs_umount(char *buf)
110*f2dd45e5SAndreas Jaekel {
111*f2dd45e5SAndreas Jaekel 	zev_zfs_umount_t *rec = (zev_zfs_umount_t *)buf;
112*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
113*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
114*f2dd45e5SAndreas Jaekel 
115*f2dd45e5SAndreas Jaekel 	printf("%s %s: guid=%llu\n",
116*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
117*f2dd45e5SAndreas Jaekel 	       rec->guid);
118*f2dd45e5SAndreas Jaekel }
119*f2dd45e5SAndreas Jaekel 
120*f2dd45e5SAndreas Jaekel static void
121*f2dd45e5SAndreas Jaekel zev_print_zvol_truncate(char *buf)
122*f2dd45e5SAndreas Jaekel {
123*f2dd45e5SAndreas Jaekel 	zev_zvol_truncate_t *rec = (zev_zvol_truncate_t *)buf;
124*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
125*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
126*f2dd45e5SAndreas Jaekel 
127*f2dd45e5SAndreas Jaekel 	printf("%s %s: guid=%llu offset=%llu length=%llu\n",
128*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
129*f2dd45e5SAndreas Jaekel 	       rec->guid,
130*f2dd45e5SAndreas Jaekel 	       rec->offset,
131*f2dd45e5SAndreas Jaekel 	       rec->length);
132*f2dd45e5SAndreas Jaekel }
133*f2dd45e5SAndreas Jaekel 
134*f2dd45e5SAndreas Jaekel static void
135*f2dd45e5SAndreas Jaekel zev_print_zvol_write(char *buf)
136*f2dd45e5SAndreas Jaekel {
137*f2dd45e5SAndreas Jaekel 	zev_print_zvol_truncate(buf);
138*f2dd45e5SAndreas Jaekel }
139*f2dd45e5SAndreas Jaekel 
140*f2dd45e5SAndreas Jaekel static void
141*f2dd45e5SAndreas Jaekel zev_print_znode_close_after_update(char *buf)
142*f2dd45e5SAndreas Jaekel {
143*f2dd45e5SAndreas Jaekel 	zev_znode_close_after_update_t *rec =
144*f2dd45e5SAndreas Jaekel 	    (zev_znode_close_after_update_t *)buf;
145*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
146*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
147*f2dd45e5SAndreas Jaekel 
148*f2dd45e5SAndreas Jaekel 	printf("%s %s: guid=%llu file=%llu.%llu\n",
149*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
150*f2dd45e5SAndreas Jaekel 	       rec->guid,
151*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
152*f2dd45e5SAndreas Jaekel }
153*f2dd45e5SAndreas Jaekel 
154*f2dd45e5SAndreas Jaekel static void
155*f2dd45e5SAndreas Jaekel zev_print_znode_create(char *buf)
156*f2dd45e5SAndreas Jaekel {
157*f2dd45e5SAndreas Jaekel 	zev_znode_create_t *rec = (zev_znode_create_t *)buf;
158*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
159*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
160*f2dd45e5SAndreas Jaekel 
161*f2dd45e5SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu file=%llu.%llu name='%s'\n",
162*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
163*f2dd45e5SAndreas Jaekel 	       rec->guid,
164*f2dd45e5SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
165*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
166*f2dd45e5SAndreas Jaekel 	       ZEV_NAME(rec));
167*f2dd45e5SAndreas Jaekel }
168*f2dd45e5SAndreas Jaekel 
169*f2dd45e5SAndreas Jaekel static void
170*f2dd45e5SAndreas Jaekel zev_print_znode_mkdir(char *buf)
171*f2dd45e5SAndreas Jaekel {
172*f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
173*f2dd45e5SAndreas Jaekel }
174*f2dd45e5SAndreas Jaekel 
175*f2dd45e5SAndreas Jaekel static void
176*f2dd45e5SAndreas Jaekel zev_print_znode_make_xattr_dir(char *buf)
177*f2dd45e5SAndreas Jaekel {
178*f2dd45e5SAndreas Jaekel 	zev_print_znode_create(buf);
179*f2dd45e5SAndreas Jaekel }
180*f2dd45e5SAndreas Jaekel 
181*f2dd45e5SAndreas Jaekel static void
182*f2dd45e5SAndreas Jaekel zev_print_znode_remove(char *buf)
183*f2dd45e5SAndreas Jaekel {
184*f2dd45e5SAndreas Jaekel 	zev_znode_remove_t *rec = (zev_znode_remove_t *)buf;
185*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
186*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
187*f2dd45e5SAndreas Jaekel 
188*f2dd45e5SAndreas Jaekel 	printf("%s %s: guid=%llu parent=%llu.%llu name='%s'\n",
189*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
190*f2dd45e5SAndreas Jaekel 	       rec->guid,
191*f2dd45e5SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
192*f2dd45e5SAndreas Jaekel 	       ZEV_NAME(rec));
193*f2dd45e5SAndreas Jaekel }
194*f2dd45e5SAndreas Jaekel 
195*f2dd45e5SAndreas Jaekel static void
196*f2dd45e5SAndreas Jaekel zev_print_znode_rmdir(char *buf)
197*f2dd45e5SAndreas Jaekel {
198*f2dd45e5SAndreas Jaekel 	zev_print_znode_remove(buf);
199*f2dd45e5SAndreas Jaekel }
200*f2dd45e5SAndreas Jaekel 
201*f2dd45e5SAndreas Jaekel static void
202*f2dd45e5SAndreas Jaekel zev_print_znode_link(char *buf)
203*f2dd45e5SAndreas Jaekel {
204*f2dd45e5SAndreas Jaekel 	zev_znode_link_t *rec = (zev_znode_link_t *)buf;
205*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
206*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
207*f2dd45e5SAndreas Jaekel 
208*f2dd45e5SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s'\n",
209*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
210*f2dd45e5SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
211*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
212*f2dd45e5SAndreas Jaekel 	       ZEV_NAME(rec));
213*f2dd45e5SAndreas Jaekel 	printf("links: %d\n", rec->file.links);
214*f2dd45e5SAndreas Jaekel }
215*f2dd45e5SAndreas Jaekel 
216*f2dd45e5SAndreas Jaekel static void
217*f2dd45e5SAndreas Jaekel zev_print_znode_symlink(char *buf)
218*f2dd45e5SAndreas Jaekel {
219*f2dd45e5SAndreas Jaekel 	zev_znode_symlink_t *rec = (zev_znode_symlink_t *)buf;
220*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
221*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
222*f2dd45e5SAndreas Jaekel 
223*f2dd45e5SAndreas Jaekel 	printf("%s %s: parent=%llu.%llu file=%llu.%llu name='%s' link='%s'\n",
224*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
225*f2dd45e5SAndreas Jaekel 	       rec->parent.ino, rec->parent.gen,
226*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
227*f2dd45e5SAndreas Jaekel 	       ZEV_NAME(rec),
228*f2dd45e5SAndreas Jaekel 	       ZEV_LINK(rec));
229*f2dd45e5SAndreas Jaekel }
230*f2dd45e5SAndreas Jaekel 
231*f2dd45e5SAndreas Jaekel static void
232*f2dd45e5SAndreas Jaekel zev_print_znode_rename(char *buf)
233*f2dd45e5SAndreas Jaekel {
234*f2dd45e5SAndreas Jaekel 	zev_znode_rename_t *rec = (zev_znode_rename_t *)buf;
235*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
236*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
237*f2dd45e5SAndreas Jaekel 
238*f2dd45e5SAndreas Jaekel 	printf("%s %s: srcdir=%llu.%llu dstdir=%llu.%llu file=%llu.%llu "
239*f2dd45e5SAndreas Jaekel 	       "srcname='%s' dstname='%s'\n",
240*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
241*f2dd45e5SAndreas Jaekel 	       rec->srcdir.ino, rec->srcdir.gen,
242*f2dd45e5SAndreas Jaekel 	       rec->dstdir.ino, rec->dstdir.gen,
243*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
244*f2dd45e5SAndreas Jaekel 	       ZEV_SRCNAME(rec),
245*f2dd45e5SAndreas Jaekel 	       ZEV_DSTNAME(rec));
246*f2dd45e5SAndreas Jaekel }
247*f2dd45e5SAndreas Jaekel 
248*f2dd45e5SAndreas Jaekel static void
249*f2dd45e5SAndreas Jaekel zev_print_znode_write(char *buf)
250*f2dd45e5SAndreas Jaekel {
251*f2dd45e5SAndreas Jaekel 	zev_znode_write_t *rec = (zev_znode_write_t *)buf;
252*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
253*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
254*f2dd45e5SAndreas Jaekel 
255*f2dd45e5SAndreas Jaekel 	printf("%s %s: file=%llu.%llu offset=%llu length=%llu\n",
256*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
257*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen,
258*f2dd45e5SAndreas Jaekel 	       rec->offset, rec->length);
259*f2dd45e5SAndreas Jaekel }
260*f2dd45e5SAndreas Jaekel 
261*f2dd45e5SAndreas Jaekel static void
262*f2dd45e5SAndreas Jaekel zev_print_znode_truncate(char *buf)
263*f2dd45e5SAndreas Jaekel {
264*f2dd45e5SAndreas Jaekel 	zev_print_znode_write(buf);
265*f2dd45e5SAndreas Jaekel }
266*f2dd45e5SAndreas Jaekel 
267*f2dd45e5SAndreas Jaekel static void
268*f2dd45e5SAndreas Jaekel zev_print_znode_setattr(char *buf)
269*f2dd45e5SAndreas Jaekel {
270*f2dd45e5SAndreas Jaekel 	zev_znode_setattr_t *rec = (zev_znode_setattr_t *)buf;
271*f2dd45e5SAndreas Jaekel 	time_t op_time = rec->op_time;
272*f2dd45e5SAndreas Jaekel 	char *ct = ctime(&op_time); ct[24] = '\0';
273*f2dd45e5SAndreas Jaekel 
274*f2dd45e5SAndreas Jaekel 	printf("%s %s: file=%llu.%llu\n",
275*f2dd45e5SAndreas Jaekel 	       ct, zev_op_name[rec->op - ZEV_OP_MIN],
276*f2dd45e5SAndreas Jaekel 	       rec->file.ino, rec->file.gen);
277*f2dd45e5SAndreas Jaekel }
278*f2dd45e5SAndreas Jaekel 
279*f2dd45e5SAndreas Jaekel static void
280*f2dd45e5SAndreas Jaekel zev_print_znode_acl(char *buf)
281*f2dd45e5SAndreas Jaekel {
282*f2dd45e5SAndreas Jaekel 	zev_print_znode_setattr(buf);
283*f2dd45e5SAndreas Jaekel }
284*f2dd45e5SAndreas Jaekel 
285*f2dd45e5SAndreas Jaekel static void
286aafc540fSAndreas Jaekel zev_print_event(char *buf, int len)
287aafc540fSAndreas Jaekel {
288*f2dd45e5SAndreas Jaekel 	int record_len;
289*f2dd45e5SAndreas Jaekel 	int op;
290aafc540fSAndreas Jaekel 
291*f2dd45e5SAndreas Jaekel 	record_len = *(uint32_t *)buf;
292*f2dd45e5SAndreas Jaekel 	if (record_len != len) {
293*f2dd45e5SAndreas Jaekel 		fprintf(stderr, "record length mismatch: got %d, expected %d\n",
294*f2dd45e5SAndreas Jaekel 		        record_len, len);
295aafc540fSAndreas Jaekel 		exit(1);
296aafc540fSAndreas Jaekel 	}
297*f2dd45e5SAndreas Jaekel 	op = *((uint32_t *)buf + 1);
298aafc540fSAndreas Jaekel 	if (op < ZEV_OP_MIN || op > ZEV_OP_MAX) {
299*f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unknown op code: %d\n", op);
300aafc540fSAndreas Jaekel 		exit(1);
301aafc540fSAndreas Jaekel 	}
302*f2dd45e5SAndreas Jaekel 	switch (op) {
303*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ERROR:
304*f2dd45e5SAndreas Jaekel 		zev_print_error(buf);
305aafc540fSAndreas Jaekel 		break;
306*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_MOUNT:
307*f2dd45e5SAndreas Jaekel 		zev_print_zfs_mount(buf);
308aafc540fSAndreas Jaekel 		break;
309*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZFS_UMOUNT:
310*f2dd45e5SAndreas Jaekel 		zev_print_zfs_umount(buf);
311aafc540fSAndreas Jaekel 		break;
312*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_TRUNCATE:
313*f2dd45e5SAndreas Jaekel 		zev_print_zvol_truncate(buf);
314aafc540fSAndreas Jaekel 		break;
315*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZVOL_WRITE:
316*f2dd45e5SAndreas Jaekel 		zev_print_zvol_write(buf);
317*f2dd45e5SAndreas Jaekel 		break;
318*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE:
319*f2dd45e5SAndreas Jaekel 		zev_print_znode_close_after_update(buf);
320*f2dd45e5SAndreas Jaekel 		break;
321*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_CREATE:
322*f2dd45e5SAndreas Jaekel 		zev_print_znode_create(buf);
323*f2dd45e5SAndreas Jaekel 		break;
324*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MKDIR:
325*f2dd45e5SAndreas Jaekel 		zev_print_znode_mkdir(buf);
326*f2dd45e5SAndreas Jaekel 		break;
327*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_MAKE_XATTR_DIR:
328*f2dd45e5SAndreas Jaekel 		zev_print_znode_make_xattr_dir(buf);
329*f2dd45e5SAndreas Jaekel 		break;
330*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_REMOVE:
331*f2dd45e5SAndreas Jaekel 		zev_print_znode_remove(buf);
332*f2dd45e5SAndreas Jaekel 		break;
333*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RMDIR:
334*f2dd45e5SAndreas Jaekel 		zev_print_znode_rmdir(buf);
335*f2dd45e5SAndreas Jaekel 		break;
336*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_LINK:
337*f2dd45e5SAndreas Jaekel 		zev_print_znode_link(buf);
338*f2dd45e5SAndreas Jaekel 		break;
339*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SYMLINK:
340*f2dd45e5SAndreas Jaekel 		zev_print_znode_symlink(buf);
341*f2dd45e5SAndreas Jaekel 		break;
342*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_RENAME:
343*f2dd45e5SAndreas Jaekel 		zev_print_znode_rename(buf);
344*f2dd45e5SAndreas Jaekel 		break;
345*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_WRITE:
346*f2dd45e5SAndreas Jaekel 		zev_print_znode_write(buf);
347*f2dd45e5SAndreas Jaekel 		break;
348*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_TRUNCATE:
349*f2dd45e5SAndreas Jaekel 		zev_print_znode_truncate(buf);
350*f2dd45e5SAndreas Jaekel 		break;
351*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_SETATTR:
352*f2dd45e5SAndreas Jaekel 		zev_print_znode_setattr(buf);
353*f2dd45e5SAndreas Jaekel 		break;
354*f2dd45e5SAndreas Jaekel 	case ZEV_OP_ZNODE_ACL:
355*f2dd45e5SAndreas Jaekel 		zev_print_znode_acl(buf);
356aafc540fSAndreas Jaekel 		break;
357aafc540fSAndreas Jaekel 	default:
358*f2dd45e5SAndreas Jaekel 		fprintf(stderr, "unhandled op code: %d\n", op);
359aafc540fSAndreas Jaekel 		exit(1);
360aafc540fSAndreas Jaekel 	}
361aafc540fSAndreas Jaekel }
362aafc540fSAndreas Jaekel 
363aafc540fSAndreas Jaekel static void
364a18c35b9SAndreas Jaekel zev_poll_events(int fd)
365a18c35b9SAndreas Jaekel {
366a18c35b9SAndreas Jaekel 	struct pollfd pfd[1];
367a18c35b9SAndreas Jaekel 	int ret;
368aafc540fSAndreas Jaekel 	char buf[4096];
369a18c35b9SAndreas Jaekel 	while (1) {
370a18c35b9SAndreas Jaekel 		pfd[0].fd = fd;
371a18c35b9SAndreas Jaekel 		pfd[0].events = POLLIN;
372a18c35b9SAndreas Jaekel 		ret = poll(pfd, 1, 1000);
373a18c35b9SAndreas Jaekel 		if (ret < 0) {
374a18c35b9SAndreas Jaekel 			perror("poll failed");
375a18c35b9SAndreas Jaekel 			exit(EXIT_FAILURE);
376a18c35b9SAndreas Jaekel 		}
377a18c35b9SAndreas Jaekel 		if (!(pfd[0].revents & POLLIN))
378a18c35b9SAndreas Jaekel 			continue;
379a18c35b9SAndreas Jaekel 		/* data available */
380a18c35b9SAndreas Jaekel 		ret = read(fd, buf, sizeof(buf));
381a18c35b9SAndreas Jaekel 		if (ret < 0) {
382a18c35b9SAndreas Jaekel 			perror("read failed");
383a18c35b9SAndreas Jaekel 			exit(EXIT_FAILURE);
384a18c35b9SAndreas Jaekel 		}
385a18c35b9SAndreas Jaekel 		if (ret == 0)
386a18c35b9SAndreas Jaekel 			continue;
387aafc540fSAndreas Jaekel 		zev_print_event(buf, ret);
388a18c35b9SAndreas Jaekel 	}
389a18c35b9SAndreas Jaekel 	return;
390a18c35b9SAndreas Jaekel }
391a18c35b9SAndreas Jaekel 
392a18c35b9SAndreas Jaekel static void
393a18c35b9SAndreas Jaekel usage(char *progname)
394a18c35b9SAndreas Jaekel {
395a18c35b9SAndreas Jaekel 	fprintf(stderr, "usage: %s [-s] [-d <dev>]\n", progname);
396a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -s         show zev statistics\n");
397a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -p         poll for ZFS events\n");
398a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -q <bytes> set maximum event queue length\n");
399fec460f8SAndreas Jaekel 	fprintf(stderr, "   -t <bytes> set queue length poll throttle\n");
400a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -m <pool>  mute pool, no events for this pool\n");
401a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -M <pool>  unmute pool\n");
402a18c35b9SAndreas Jaekel 	fprintf(stderr, "   -d <dev>   device file to use. default is '%s'\n",
403a18c35b9SAndreas Jaekel 	    ZEV_DEVICE);
404a18c35b9SAndreas Jaekel 	exit (EXIT_FAILURE);
405a18c35b9SAndreas Jaekel }
406a18c35b9SAndreas Jaekel 
407a18c35b9SAndreas Jaekel static int
408a18c35b9SAndreas Jaekel zev_set_max_queue_len(int fd, char *optarg)
409a18c35b9SAndreas Jaekel {
410a18c35b9SAndreas Jaekel 	uint64_t maxqueuelen;
411a18c35b9SAndreas Jaekel 
412a18c35b9SAndreas Jaekel 	errno = 0;
413a18c35b9SAndreas Jaekel 	maxqueuelen = strtol(optarg, (char **)NULL, 10);
414a18c35b9SAndreas Jaekel 	if (errno) {
415a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
416a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
417a18c35b9SAndreas Jaekel 	}
418a18c35b9SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_MAX_QUEUE_LEN, &maxqueuelen)) {
419a18c35b9SAndreas Jaekel 		perror("setting max queue length failed");
420a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
421a18c35b9SAndreas Jaekel 	}
422a18c35b9SAndreas Jaekel 	return (0);
423a18c35b9SAndreas Jaekel }
424a18c35b9SAndreas Jaekel 
425a18c35b9SAndreas Jaekel static int
426fec460f8SAndreas Jaekel zev_set_poll_wakeup_queue_len(int fd, char *optarg)
427fec460f8SAndreas Jaekel {
428fec460f8SAndreas Jaekel 	uint64_t queuelen;
429fec460f8SAndreas Jaekel 
430fec460f8SAndreas Jaekel 	errno = 0;
431fec460f8SAndreas Jaekel 	queuelen = strtol(optarg, (char **)NULL, 10);
432fec460f8SAndreas Jaekel 	if (errno) {
433fec460f8SAndreas Jaekel 		fprintf(stderr, "invalid queue length parameter: %s\n", optarg);
434fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
435fec460f8SAndreas Jaekel 	}
436fec460f8SAndreas Jaekel 	if (ioctl(fd, ZEV_IOC_SET_POLL_WAKEUP_QUEUE_LEN, &queuelen)) {
437fec460f8SAndreas Jaekel 		perror("setting poll wakeup queue length failed");
438fec460f8SAndreas Jaekel 		return (EXIT_FAILURE);
439fec460f8SAndreas Jaekel 	}
440fec460f8SAndreas Jaekel 	return (0);
441fec460f8SAndreas Jaekel }
442fec460f8SAndreas Jaekel 
443fec460f8SAndreas Jaekel static int
444a18c35b9SAndreas Jaekel zev_mute_unmute_impl(int fd, char *poolname, int mute)
445a18c35b9SAndreas Jaekel {
446a18c35b9SAndreas Jaekel 	zev_ioctl_poolarg_t pa;
447a18c35b9SAndreas Jaekel 	int len;
448a18c35b9SAndreas Jaekel 	int op = mute ? ZEV_IOC_MUTE_POOL : ZEV_IOC_UNMUTE_POOL;
449a18c35b9SAndreas Jaekel 	len = strlen(poolname);
450a18c35b9SAndreas Jaekel 	if (len <= 0 || len >= sizeof(pa.zev_poolname)) {
451a18c35b9SAndreas Jaekel 		fprintf(stderr, "invalid poolname: %s\n", poolname);
452a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
453a18c35b9SAndreas Jaekel 	}
454a18c35b9SAndreas Jaekel 	strcpy(pa.zev_poolname, poolname);
455a18c35b9SAndreas Jaekel 	pa.zev_poolname_len = len;
456a18c35b9SAndreas Jaekel 	if (ioctl(fd, op, &pa)) {
457a18c35b9SAndreas Jaekel 		perror("muting pool data failed");
458a18c35b9SAndreas Jaekel 		return (EXIT_FAILURE);
459a18c35b9SAndreas Jaekel 	}
460a18c35b9SAndreas Jaekel 	return (0);
461a18c35b9SAndreas Jaekel }
462a18c35b9SAndreas Jaekel 
463a18c35b9SAndreas Jaekel int
464a18c35b9SAndreas Jaekel zev_mute_pool(int fd, char *poolname)
465a18c35b9SAndreas Jaekel {
466a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 1);
467a18c35b9SAndreas Jaekel }
468a18c35b9SAndreas Jaekel 
469a18c35b9SAndreas Jaekel int
470a18c35b9SAndreas Jaekel zev_unmute_pool(int fd, char *poolname)
471a18c35b9SAndreas Jaekel {
472a18c35b9SAndreas Jaekel 	return zev_mute_unmute_impl(fd, poolname, 0);
473a18c35b9SAndreas Jaekel }
474a18c35b9SAndreas Jaekel 
475a18c35b9SAndreas Jaekel int
476a18c35b9SAndreas Jaekel main(int argc, char **argv)
477a18c35b9SAndreas Jaekel {
478a18c35b9SAndreas Jaekel 	int fd;
479a18c35b9SAndreas Jaekel 	int c;
480a18c35b9SAndreas Jaekel 	int ops = 0;
481a18c35b9SAndreas Jaekel 	extern char *optarg;
482a18c35b9SAndreas Jaekel 
483a18c35b9SAndreas Jaekel 	/* open device */
484a18c35b9SAndreas Jaekel 	fd = open(zev_device, O_RDONLY);
485a18c35b9SAndreas Jaekel 	if (fd < 0) {
486a18c35b9SAndreas Jaekel 		perror("opening zev device failed");
487a18c35b9SAndreas Jaekel 		return EXIT_FAILURE;
488a18c35b9SAndreas Jaekel 	}
489fec460f8SAndreas Jaekel 	while ((c = getopt(argc, argv, "spdq:t:m:M:h?")) != -1) {
490a18c35b9SAndreas Jaekel 		switch(c) {
491a18c35b9SAndreas Jaekel 		case 's':
492a18c35b9SAndreas Jaekel 			ops |= OP_STATISTICS;
493a18c35b9SAndreas Jaekel 			break;
494a18c35b9SAndreas Jaekel 		case 'p':
495a18c35b9SAndreas Jaekel 			ops |= OP_POLL_EVENTS;
496a18c35b9SAndreas Jaekel 			break;
497a18c35b9SAndreas Jaekel 		case 'd':
498a18c35b9SAndreas Jaekel 			zev_device = optarg;
499a18c35b9SAndreas Jaekel 			break;
500a18c35b9SAndreas Jaekel 		case 'q':
501a18c35b9SAndreas Jaekel 			return zev_set_max_queue_len(fd, optarg);
502fec460f8SAndreas Jaekel 		case 't':
503fec460f8SAndreas Jaekel 			return zev_set_poll_wakeup_queue_len(fd, optarg);
504a18c35b9SAndreas Jaekel 		case 'm':
505a18c35b9SAndreas Jaekel 			return zev_mute_pool(fd, optarg);
506a18c35b9SAndreas Jaekel 		case 'M':
507a18c35b9SAndreas Jaekel 			return zev_unmute_pool(fd, optarg);
508a18c35b9SAndreas Jaekel 		case 'h':
509a18c35b9SAndreas Jaekel 		case '?':
510a18c35b9SAndreas Jaekel 		default:
511a18c35b9SAndreas Jaekel 			usage(argv[0]);
512a18c35b9SAndreas Jaekel 		}
513a18c35b9SAndreas Jaekel 	}
514a18c35b9SAndreas Jaekel 	if (!ops)
515a18c35b9SAndreas Jaekel 		usage(argv[0]);
516a18c35b9SAndreas Jaekel 	if (ops & OP_STATISTICS)
517a18c35b9SAndreas Jaekel 		zev_statistics(fd);
518a18c35b9SAndreas Jaekel 	if (ops & OP_POLL_EVENTS)
519a18c35b9SAndreas Jaekel 		zev_poll_events(fd);
520a18c35b9SAndreas Jaekel 	close(fd);
521a18c35b9SAndreas Jaekel 	return EXIT_SUCCESS;
522a18c35b9SAndreas Jaekel }
523a18c35b9SAndreas Jaekel 
524