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