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