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