xref: /titanic_44/usr/src/uts/common/fs/zev/zev_callbacks.c (revision 205ed6bf74195aecd25276f8e00fff2f8b47a58e)
1 #include <sys/mode.h>
2 #include <sys/zfs_znode.h>
3 #include <sys/fs/zfs.h>
4 #include <sys/fs/zev.h>
5 #include <sys/zfs_events.h>
6 #include <sys/zev_checksums.h>
7 
8 #define ZEV_FILL_INODE_INFO(name, znode)				\
9 	do {								\
10 		uint64_t mtime[2], ctime[2];				\
11 		sa_bulk_attr_t bulk[2];					\
12 		int count = 0;						\
13 		timestruc_t mtime_s, ctime_s;				\
14 		SA_ADD_BULK_ATTR(bulk, count,				\
15 			         SA_ZPL_MTIME(znode->z_zfsvfs),		\
16 		                 NULL, &mtime, 16);			\
17 		SA_ADD_BULK_ATTR(bulk, count,				\
18 			         SA_ZPL_CTIME(znode->z_zfsvfs),		\
19 		                 NULL, &ctime, 16);			\
20 		if ((sa_bulk_lookup(znode->z_sa_hdl, bulk, count)) != 0) { \
21 			zev_queue_error(op, "znode write: "		\
22 			                "mtime/ctime unavailable");	\
23 			/* continue anyway, use fake data */		\
24 			mtime_s.tv_sec = ctime_s.tv_sec = 0;		\
25 		}							\
26 		ZFS_TIME_DECODE(&mtime_s, mtime);			\
27 		ZFS_TIME_DECODE(&ctime_s, ctime);			\
28 		rec->name.ino = znode->z_id;				\
29 		rec->name.gen = znode->z_gen;				\
30 		rec->name.mtime = mtime_s.tv_sec;			\
31 		rec->name.ctime = ctime_s.tv_sec;			\
32 		rec->name.size = znode->z_size;				\
33 		rec->name.type = znode->z_vnode->v_type;		\
34 		rec->name.mode =					\
35 			znode->z_mode | VTTOIF(znode->z_vnode->v_type);	\
36 		rec->name.links = znode->z_links;			\
37 		rec->name.flags = znode->z_pflags & ZFS_XATTR ?		\
38 			ZEV_FL_XATTR : 0;				\
39 	} while(0)
40 
41 void
42 zev_zfs_mount_cb(vfs_t *vfs, vnode_t *mpt, char *dataset, boolean_t remount)
43 {
44 	int op = ZEV_OP_ZFS_MOUNT;
45 	char mountpoint[MAXPATHLEN+1];
46 	int mountpoint_len;
47 	int dataset_len;
48 	zev_zfs_mount_t *rec;
49 	zev_msg_t *msg = NULL;
50 	int msg_size;
51 	znode_t *zp_root;
52 
53 	zfsvfs_t *zfsvfs = (zfsvfs_t *)vfs->vfs_data;
54 	if (dsl_dataset_is_snapshot(zfsvfs->z_os->os_dsl_dataset))
55 		return;
56 	if (zev_skip_pool(zfsvfs->z_os))
57 		return;
58 	/* expensive, but we don't have many mount ops. */
59 	if ((vnodetopath(NULL, mpt, mountpoint, sizeof(mountpoint),
60 	    kcred)) != 0) {
61 		zev_queue_error(op, "unresolvable mountpoint, dataset=%s",
62 		                dataset);
63 		return;
64 	}
65 	if (zfs_zget(zfsvfs, zfsvfs->z_root, &zp_root) != 0) {
66 		zev_queue_error(op, "can't get root znode, dataset=%s",
67 		                dataset);
68 		return;
69 	}
70 
71 	dataset_len = strlen(dataset);
72 	mountpoint_len = strlen(mountpoint);
73 	msg_size = sizeof(*rec) + dataset_len + 1 + mountpoint_len + 1;
74 	msg = zev_alloc(sizeof(*msg) + msg_size);
75 	msg->size = msg_size;
76 	rec = (zev_zfs_mount_t *)(msg + 1);
77 	rec->record_len = msg_size;
78 	rec->op = op;
79 	rec->op_time = ddi_get_time();
80 	rec->guid = zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
81 	rec->remount = remount;
82 	rec->dataset_len = dataset_len;
83 	rec->mountpoint_len = mountpoint_len;
84 	ZEV_FILL_INODE_INFO(root, zp_root);
85 	VN_RELE(ZTOV(zp_root));
86 	(void) memcpy(ZEV_DATASET(rec), dataset, dataset_len + 1);
87 	(void) memcpy(ZEV_MOUNTPOINT(rec), mountpoint, mountpoint_len + 1);
88 	zev_queue_message(op, msg);
89 }
90 
91 void
92 zev_zfs_umount_cb(vfs_t *vfs)
93 {
94 	int op = ZEV_OP_ZFS_UMOUNT;
95 	zev_zfs_umount_t *rec;
96 	zev_msg_t *msg = NULL;
97 	int msg_size;
98 
99 	zfsvfs_t *zfsvfs = (zfsvfs_t *)vfs->vfs_data;
100 	if (dsl_dataset_is_snapshot(zfsvfs->z_os->os_dsl_dataset))
101 		return;
102 	if (zev_skip_pool(zfsvfs->z_os))
103 		return;
104 
105 	msg_size = sizeof(*rec);
106 	msg = zev_alloc(sizeof(*msg) + msg_size);
107 	msg->size = msg_size;
108 	rec = (zev_zfs_umount_t *)(msg + 1);
109 	rec->record_len = msg_size;
110 	rec->op = op;
111 	rec->op_time = ddi_get_time();
112 	rec->guid = zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
113 	zev_queue_message(op, msg);
114 }
115 
116 void
117 zev_zvol_truncate_cb(char *dataset, objset_t *os, uint64_t off, uint64_t len)
118 {
119 	int op = ZEV_OP_ZVOL_TRUNCATE;
120 	zev_zvol_truncate_t *rec;
121 	zev_msg_t *msg = NULL;
122 	int msg_size;
123 	int dataset_len;
124 
125 	if (zev_skip_pool(os))
126 		return;
127 
128 	dataset_len = strlen(dataset);
129 	msg_size = sizeof(*rec) + dataset_len + 1;
130 	msg = zev_alloc(sizeof(*msg) + msg_size);
131 	msg->size = msg_size;
132 	rec = (zev_zvol_truncate_t *)(msg + 1);
133 	rec->record_len = msg_size;
134 	rec->op = op;
135 	rec->op_time = ddi_get_time();
136 	rec->guid = os->os_dsl_dataset->ds_phys->ds_guid;
137 	rec->offset = off;
138 	rec->length = len;
139 	rec->dataset_len = dataset_len;
140 	(void) memcpy(ZEV_DATASET(rec), dataset, dataset_len + 1);
141 	zev_queue_message(op, msg);
142 }
143 
144 void
145 zev_zvol_write_cb(char *dataset, objset_t *os, uint64_t off, uint64_t len)
146 {
147 	int op = ZEV_OP_ZVOL_WRITE;
148 	zev_zvol_write_t *rec;
149 	zev_msg_t *msg = NULL;
150 	int msg_size;
151 	int dataset_len;
152 
153 	if (zev_skip_pool(os))
154 		return;
155 
156 	dataset_len = strlen(dataset);
157 	msg_size = sizeof(*rec) + dataset_len + 1;
158 	msg = zev_alloc(sizeof(*msg) + msg_size);
159 	msg->size = msg_size;
160 	rec = (zev_zvol_write_t *)(msg + 1);
161 	rec->record_len = msg_size;
162 	rec->op = op;
163 	rec->op_time = ddi_get_time();
164 	rec->guid = os->os_dsl_dataset->ds_phys->ds_guid;
165 	rec->offset = off;
166 	rec->length = len;
167 	rec->dataset_len = dataset_len;
168 	(void) memcpy(ZEV_DATASET(rec), dataset, dataset_len + 1);
169 	zev_queue_message(op, msg);
170 }
171 
172 void
173 zev_znode_close_after_update_cb(znode_t *zp)
174 {
175 	int op = ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE;
176 	zev_znode_close_after_update_t *rec;
177 	zev_msg_t *msg = NULL;
178 	int msg_size;
179 
180 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
181 		return;
182 
183 	msg_size = sizeof(*rec);
184 	msg = zev_alloc(sizeof(*msg) + msg_size);
185 	msg->size = msg_size;
186 	rec = (zev_znode_close_after_update_t *)(msg + 1);
187 	rec->record_len = msg_size;
188 	rec->op = op;
189 	rec->op_time = ddi_get_time();
190 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
191 	ZEV_FILL_INODE_INFO(file, zp);
192 	zev_queue_message(op, msg);
193 }
194 
195 void
196 zev_znode_create_cb(znode_t *dzp, znode_t *zp, char *name, uint64_t txtype)
197 {
198 	int op = ZEV_OP_ZNODE_CREATE;
199 	zev_znode_create_t *rec;
200 	zev_msg_t *msg = NULL;
201 	int msg_size;
202 	int name_len;
203 
204 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
205 		return;
206 
207 	int type = (int)txtype;
208 	switch(type) {
209 	case TX_CREATE:
210 	case TX_CREATE_ACL:
211 	case TX_CREATE_ATTR:
212 	case TX_CREATE_ACL_ATTR:
213 		op = ZEV_OP_ZNODE_CREATE;
214 		break;
215 	case TX_MKDIR:
216 	case TX_MKDIR_ACL:
217 	case TX_MKDIR_ATTR:
218 	case TX_MKDIR_ACL_ATTR:
219 		op = ZEV_OP_ZNODE_MKDIR;
220 		break;
221 	case TX_MKXATTR:
222 		op = ZEV_OP_ZNODE_MAKE_XATTR_DIR;
223 		break;
224 	default:
225 		zev_queue_error(ZEV_OP_ZNODE_CREATE,
226 		    "ERROR: ZNODE_CREATE: unknown txtype %d "
227 		    "(dir_inode=%d:%d inode=%d:%d name='%s')\n",
228 		    type,
229 		    dzp->z_gen,
230 		    dzp->z_id,
231 		    zp->z_gen,
232 		    zp->z_id,
233 		    name);
234 		return;
235 	}
236 
237 	/* all three types use the same struct, so this works for all types: */
238 	name_len = strlen(name);
239 	msg_size = sizeof(*rec) + name_len + 1;
240 	msg = zev_alloc(sizeof(*msg) + msg_size);
241 	msg->size = msg_size;
242 	rec = (zev_znode_create_t *)(msg + 1);
243 	rec->record_len = msg_size;
244 	rec->op = op;
245 	rec->op_time = ddi_get_time();
246 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
247 	ZEV_FILL_INODE_INFO(parent, dzp);
248 	ZEV_FILL_INODE_INFO(file, zp);
249 	rec->name_len = name_len;
250 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
251 	zev_queue_message(op, msg);
252 }
253 
254 void
255 zev_znode_remove_cb(znode_t *dzp, znode_t *zp, char *name, uint64_t txtype)
256 {
257 	int op = ZEV_OP_ZNODE_REMOVE;
258 	zev_znode_remove_t *rec;
259 	zev_msg_t *msg = NULL;
260 	int msg_size;
261 	int name_len;
262 
263 	if (zev_skip_pool(dzp->z_zfsvfs->z_os))
264 		return;
265 
266 	int type = (int)txtype;
267 	switch(type) {
268 	case TX_REMOVE:
269 		op = ZEV_OP_ZNODE_REMOVE;
270 		break;
271 	case TX_RMDIR:
272 		op = ZEV_OP_ZNODE_RMDIR;
273 		break;
274 	default:
275 		zev_queue_error(ZEV_OP_ZNODE_REMOVE,
276 		    "ERROR: ZNODE_REMOVE: unknown txtype %d "
277 		    "(dir_inode=%d:%d name='%s')\n",
278 		    type,
279 		    dzp->z_gen,
280 		    dzp->z_id,
281 		    name);
282 		return;
283 	}
284 
285 	/* both types use the same struct, so this works for all types: */
286 	name_len = strlen(name);
287 	msg_size = sizeof(*rec) + name_len + 1;
288 	msg = zev_alloc(sizeof(*msg) + msg_size);
289 	msg->size = msg_size;
290 	rec = (zev_znode_remove_t *)(msg + 1);
291 	rec->record_len = msg_size;
292 	rec->op = op;
293 	rec->op_time = ddi_get_time();
294 	rec->guid = dzp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
295 	ZEV_FILL_INODE_INFO(file, zp);
296 	ZEV_FILL_INODE_INFO(parent, dzp);
297 	rec->name_len = name_len;
298 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
299 	zev_queue_message(op, msg);
300 }
301 
302 void
303 zev_znode_link_cb(znode_t *dzp, znode_t *zp, char *name)
304 {
305 	int op = ZEV_OP_ZNODE_LINK;
306 	zev_znode_link_t *rec;
307 	zev_msg_t *msg = NULL;
308 	int msg_size;
309 	int name_len;
310 
311 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
312 		return;
313 
314 	name_len = strlen(name);
315 	msg_size = sizeof(*rec) + name_len + 1;
316 	msg = zev_alloc(sizeof(*msg) + msg_size);
317 	msg->size = msg_size;
318 	rec = (zev_znode_link_t *)(msg + 1);
319 	rec->record_len = msg_size;
320 	rec->op = op;
321 	rec->op_time = ddi_get_time();
322 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
323 	ZEV_FILL_INODE_INFO(parent, dzp);
324 	ZEV_FILL_INODE_INFO(file, zp);
325 	rec->name_len = name_len;
326 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
327 	zev_queue_message(op, msg);
328 }
329 
330 void
331 zev_znode_symlink_cb(znode_t *dzp, znode_t *zp, char *name, char *link)
332 {
333 	int op = ZEV_OP_ZNODE_SYMLINK;
334 	zev_znode_symlink_t *rec;
335 	zev_msg_t *msg = NULL;
336 	int msg_size;
337 	int name_len;
338 	int link_len;
339 
340 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
341 		return;
342 
343 	name_len = strlen(name);
344 	link_len = strlen(link);
345 	msg_size = sizeof(*rec) + name_len + 1 + link_len + 1;
346 	msg = zev_alloc(sizeof(*msg) + msg_size);
347 	msg->size = msg_size;
348 	rec = (zev_znode_symlink_t *)(msg + 1);
349 	rec->record_len = msg_size;
350 	rec->op = op;
351 	rec->op_time = ddi_get_time();
352 	rec->guid = dzp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
353 	ZEV_FILL_INODE_INFO(parent, dzp);
354 	ZEV_FILL_INODE_INFO(file, zp);
355 	rec->name_len = name_len;
356 	rec->link_len = link_len;
357 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
358 	(void) memcpy(ZEV_LINK(rec), link, link_len + 1);
359 	zev_queue_message(op, msg);
360 }
361 
362 void
363 zev_znode_rename_cb(znode_t *sdzp, char *sname, znode_t *tdzp,
364     char *tname, znode_t *szp)
365 {
366 	int op = ZEV_OP_ZNODE_RENAME;
367 	zev_znode_rename_t *rec;
368 	zev_msg_t *msg = NULL;
369 	int msg_size;
370 	int srcname_len;
371 	int dstname_len;
372 
373 	if (zev_skip_pool(szp->z_zfsvfs->z_os))
374 		return;
375 
376 	srcname_len = strlen(sname);
377 	dstname_len = strlen(tname);
378 	msg_size = sizeof(*rec) + srcname_len + 1 + dstname_len + 1;
379 	msg = zev_alloc(sizeof(*msg) + msg_size);
380 	msg->size = msg_size;
381 	rec = (zev_znode_rename_t *)(msg + 1);
382 	rec->record_len = msg_size;
383 	rec->op = op;
384 	rec->op_time = ddi_get_time();
385 	rec->guid = szp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
386 	ZEV_FILL_INODE_INFO(srcdir, sdzp);
387 	ZEV_FILL_INODE_INFO(dstdir, tdzp);
388 	ZEV_FILL_INODE_INFO(file, szp);
389 	rec->srcname_len = srcname_len;
390 	rec->dstname_len = dstname_len;
391 	(void) memcpy(ZEV_SRCNAME(rec), sname, srcname_len + 1);
392 	(void) memcpy(ZEV_DSTNAME(rec), tname, dstname_len + 1);
393 	zev_queue_message(op, msg);
394 }
395 
396 void
397 zev_znode_write_cb(znode_t *zp, uint64_t off, uint64_t len)
398 {
399 	int op = ZEV_OP_ZNODE_WRITE;
400 	zev_znode_write_t *rec;
401 	zev_msg_t *msg = NULL;
402 	int msg_size;
403 	zev_sig_t *sig_buf;
404 	uint64_t sig_buf_len;
405 	uint64_t sig_len;
406 	uint64_t sig_cnt;
407 	int ret;
408 
409 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
410 		return;
411 
412 	ret = zev_get_checksums(&sig_buf, &sig_buf_len, &sig_cnt,
413 	                        zp, off, len, zev_write);
414 	if (ret) {
415 		zev_queue_error(op,
416 		    "ERROR: ZNODE_WRITE: can't get checksum (inode=%d:%d)\n",
417 		    zp->z_gen,
418 		    zp->z_id);
419 		return;
420 	}
421 	sig_len = sig_cnt * sizeof(zev_sig_t);
422 
423 	msg_size = sizeof(*rec) + sig_len;
424 	msg = zev_alloc(sizeof(*msg) + msg_size);
425 	msg->size = msg_size;
426 	rec = (zev_znode_write_t *)(msg + 1);
427 	rec->record_len = msg_size;
428 	rec->op = op;
429 	rec->op_time = ddi_get_time();
430 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
431 	ZEV_FILL_INODE_INFO(file, zp);
432 	rec->offset = off;
433 	rec->length = len;
434 	rec->signature_cnt = sig_cnt;
435 	if (sig_cnt && sig_buf) {
436 		memcpy(ZEV_SIGNATURES(rec), sig_buf, sig_len);
437 		zev_free(sig_buf, sig_buf_len);
438 	}
439 	zev_queue_message(op, msg);
440 }
441 
442 void
443 zev_znode_truncate_cb(znode_t *zp, uint64_t off, uint64_t len)
444 {
445 	int op = ZEV_OP_ZNODE_TRUNCATE;
446 	zev_znode_truncate_t *rec;
447 	zev_msg_t *msg = NULL;
448 	int msg_size;
449 	zev_sig_t *sig_buf;
450 	uint64_t sig_buf_len;
451 	uint64_t sig_len;
452 	uint64_t sig_cnt;
453 	int ret;
454 
455 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
456 		return;
457 
458 	ret = zev_get_checksums(&sig_buf, &sig_buf_len, &sig_cnt,
459 	                        zp, off, len, zev_truncate);
460 	if (ret) {
461 		zev_queue_error(op,
462 		    "ERROR: ZNODE_TRUNCATE: can't get checksum (inode=%d:%d)\n",
463 		    zp->z_gen,
464 		    zp->z_id);
465 		return;
466 	}
467 	sig_len = sig_cnt * sizeof(zev_sig_t);
468 
469 	msg_size = sizeof(*rec) + sig_len;
470 	msg = zev_alloc(sizeof(*msg) + msg_size);
471 	msg->size = msg_size;
472 	rec = (zev_znode_truncate_t *)(msg + 1);
473 	rec->record_len = msg_size;
474 	rec->op = op;
475 	rec->op_time = ddi_get_time();
476 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
477 	ZEV_FILL_INODE_INFO(file, zp);
478 	rec->offset = off;
479 	rec->length = len;
480 	rec->signature_cnt = sig_cnt;
481 	if (sig_cnt && sig_buf) {
482 		memcpy(ZEV_SIGNATURES(rec), sig_buf, sig_len);
483 		zev_free(sig_buf, sig_buf_len);
484 	}
485 	zev_queue_message(op, msg);
486 }
487 
488 void
489 zev_znode_setattr_cb(znode_t *zp)
490 {
491 	int op = ZEV_OP_ZNODE_SETATTR;
492 	zev_znode_setattr_t *rec;
493 	zev_msg_t *msg = NULL;
494 	int msg_size;
495 
496 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
497 		return;
498 
499 	msg_size = sizeof(*rec);
500 	msg = zev_alloc(sizeof(*msg) + msg_size);
501 	msg->size = msg_size;
502 	rec = (zev_znode_setattr_t *)(msg + 1);
503 	rec->record_len = msg_size;
504 	rec->op = op;
505 	rec->op_time = ddi_get_time();
506 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
507 	ZEV_FILL_INODE_INFO(file, zp);
508 	zev_queue_message(op, msg);
509 }
510 
511 void
512 zev_znode_acl_cb(znode_t *zp)
513 {
514 	int op = ZEV_OP_ZNODE_ACL;
515 	zev_znode_acl_t *rec;
516 	zev_msg_t *msg = NULL;
517 	int msg_size;
518 
519 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
520 		return;
521 
522 	msg_size = sizeof(*rec);
523 	msg = zev_alloc(sizeof(*msg) + msg_size);
524 	msg->size = msg_size;
525 	rec = (zev_znode_acl_t *)(msg + 1);
526 	rec->record_len = msg_size;
527 	rec->op = op;
528 	rec->op_time = ddi_get_time();
529 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
530 	ZEV_FILL_INODE_INFO(file, zp);
531 	zev_queue_message(op, msg);
532 }
533 
534 rz_zev_callbacks_t zev_callbacks = {
535 	/* zfsvfs events */
536 	.rz_zev_zfs_mount                = zev_zfs_mount_cb,
537 	.rz_zev_zfs_umount               = zev_zfs_umount_cb,
538 
539 	/* zvol zil events */
540 	.rz_zev_zvol_truncate            = zev_zvol_truncate_cb,
541 	.rz_zev_zvol_write               = zev_zvol_write_cb,
542 
543 	/* znode zil events */
544 	.rz_zev_znode_close_after_update = zev_znode_close_after_update_cb,
545 	.rz_zev_znode_create             = zev_znode_create_cb,
546 	.rz_zev_znode_remove             = zev_znode_remove_cb,
547 	.rz_zev_znode_link               = zev_znode_link_cb,
548 	.rz_zev_znode_symlink            = zev_znode_symlink_cb,
549 	.rz_zev_znode_rename             = zev_znode_rename_cb,
550 	.rz_zev_znode_write              = zev_znode_write_cb,
551 	.rz_zev_znode_truncate           = zev_znode_truncate_cb,
552 	.rz_zev_znode_setattr            = zev_znode_setattr_cb,
553 	.rz_zev_znode_acl                = zev_znode_acl_cb,
554 };
555 
556