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