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