xref: /titanic_51/usr/src/uts/common/fs/zev/zev_callbacks.c (revision 80c8f7fad26095c315669ecdfbb0e9c09527c506)
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, znode_t *zp, 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(file, zp);
288 	ZEV_FILL_INODE_INFO(parent, dzp);
289 	rec->name_len = name_len;
290 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
291 	zev_queue_message(op, msg);
292 }
293 
294 void
295 zev_znode_link_cb(znode_t *dzp, znode_t *zp, char *name)
296 {
297 	int op = ZEV_OP_ZNODE_LINK;
298 	zev_znode_link_t *rec;
299 	zev_msg_t *msg = NULL;
300 	int msg_size;
301 	int name_len;
302 
303 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
304 		return;
305 
306 	name_len = strlen(name);
307 	msg_size = sizeof(*rec) + name_len + 1;
308 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
309 	msg->size = msg_size;
310 	rec = (zev_znode_link_t *)(msg + 1);
311 	rec->record_len = msg_size;
312 	rec->op = op;
313 	rec->op_time = ddi_get_time();
314 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
315 	ZEV_FILL_INODE_INFO(parent, dzp);
316 	ZEV_FILL_INODE_INFO(file, zp);
317 	rec->name_len = name_len;
318 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
319 	zev_queue_message(op, msg);
320 }
321 
322 void
323 zev_znode_symlink_cb(znode_t *dzp, znode_t *zp, char *name, char *link)
324 {
325 	int op = ZEV_OP_ZNODE_SYMLINK;
326 	zev_znode_symlink_t *rec;
327 	zev_msg_t *msg = NULL;
328 	int msg_size;
329 	int name_len;
330 	int link_len;
331 
332 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
333 		return;
334 
335 	name_len = strlen(name);
336 	link_len = strlen(link);
337 	msg_size = sizeof(*rec) + name_len + 1 + link_len + 1;
338 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
339 	msg->size = msg_size;
340 	rec = (zev_znode_symlink_t *)(msg + 1);
341 	rec->record_len = msg_size;
342 	rec->op = op;
343 	rec->op_time = ddi_get_time();
344 	rec->guid = dzp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
345 	ZEV_FILL_INODE_INFO(parent, dzp);
346 	ZEV_FILL_INODE_INFO(file, zp);
347 	rec->name_len = name_len;
348 	rec->link_len = link_len;
349 	(void) memcpy(ZEV_NAME(rec), name, name_len + 1);
350 	(void) memcpy(ZEV_LINK(rec), link, link_len + 1);
351 	zev_queue_message(op, msg);
352 }
353 
354 void
355 zev_znode_rename_cb(znode_t *sdzp, char *sname, znode_t *tdzp,
356     char *tname, znode_t *szp)
357 {
358 	int op = ZEV_OP_ZNODE_RENAME;
359 	zev_znode_rename_t *rec;
360 	zev_msg_t *msg = NULL;
361 	int msg_size;
362 	int srcname_len;
363 	int dstname_len;
364 
365 	if (zev_skip_pool(szp->z_zfsvfs->z_os))
366 		return;
367 
368 	srcname_len = strlen(sname);
369 	dstname_len = strlen(tname);
370 	msg_size = sizeof(*rec) + srcname_len + 1 + dstname_len + 1;
371 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
372 	msg->size = msg_size;
373 	rec = (zev_znode_rename_t *)(msg + 1);
374 	rec->record_len = msg_size;
375 	rec->op = op;
376 	rec->op_time = ddi_get_time();
377 	rec->guid = szp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
378 	ZEV_FILL_INODE_INFO(srcdir, sdzp);
379 	ZEV_FILL_INODE_INFO(dstdir, tdzp);
380 	ZEV_FILL_INODE_INFO(file, szp);
381 	rec->srcname_len = srcname_len;
382 	rec->dstname_len = dstname_len;
383 	(void) memcpy(ZEV_SRCNAME(rec), sname, srcname_len + 1);
384 	(void) memcpy(ZEV_DSTNAME(rec), tname, dstname_len + 1);
385 	zev_queue_message(op, msg);
386 }
387 
388 void
389 zev_znode_write_cb(znode_t *zp, uint64_t off, uint64_t len)
390 {
391 	int op = ZEV_OP_ZNODE_WRITE;
392 	zev_znode_write_t *rec;
393 	zev_msg_t *msg = NULL;
394 	int msg_size;
395 
396 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
397 		return;
398 
399 	msg_size = sizeof(*rec);
400 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
401 	msg->size = msg_size;
402 	rec = (zev_znode_write_t *)(msg + 1);
403 	rec->record_len = msg_size;
404 	rec->op = op;
405 	rec->op_time = ddi_get_time();
406 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
407 	ZEV_FILL_INODE_INFO(file, zp);
408 	rec->offset = off;
409 	rec->length = len;
410 	zev_queue_message(op, msg);
411 }
412 
413 void
414 zev_znode_truncate_cb(znode_t *zp, uint64_t off, uint64_t len)
415 {
416 	int op = ZEV_OP_ZNODE_TRUNCATE;
417 	zev_znode_truncate_t *rec;
418 	zev_msg_t *msg = NULL;
419 	int msg_size;
420 
421 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
422 		return;
423 
424 	msg_size = sizeof(*rec);
425 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
426 	msg->size = msg_size;
427 	rec = (zev_znode_truncate_t *)(msg + 1);
428 	rec->record_len = msg_size;
429 	rec->op = op;
430 	rec->op_time = ddi_get_time();
431 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
432 	ZEV_FILL_INODE_INFO(file, zp);
433 	rec->offset = off;
434 	rec->length = len;
435 	zev_queue_message(op, msg);
436 }
437 
438 void
439 zev_znode_setattr_cb(znode_t *zp)
440 {
441 	int op = ZEV_OP_ZNODE_SETATTR;
442 	zev_znode_setattr_t *rec;
443 	zev_msg_t *msg = NULL;
444 	int msg_size;
445 
446 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
447 		return;
448 
449 	msg_size = sizeof(*rec);
450 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
451 	msg->size = msg_size;
452 	rec = (zev_znode_setattr_t *)(msg + 1);
453 	rec->record_len = msg_size;
454 	rec->op = op;
455 	rec->op_time = ddi_get_time();
456 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
457 	ZEV_FILL_INODE_INFO(file, zp);
458 	zev_queue_message(op, msg);
459 }
460 
461 void
462 zev_znode_acl_cb(znode_t *zp)
463 {
464 	int op = ZEV_OP_ZNODE_ACL;
465 	zev_znode_acl_t *rec;
466 	zev_msg_t *msg = NULL;
467 	int msg_size;
468 
469 	if (zev_skip_pool(zp->z_zfsvfs->z_os))
470 		return;
471 
472 	msg_size = sizeof(*rec);
473 	msg = kmem_alloc(sizeof(*msg) + msg_size, KM_SLEEP);
474 	msg->size = msg_size;
475 	rec = (zev_znode_acl_t *)(msg + 1);
476 	rec->record_len = msg_size;
477 	rec->op = op;
478 	rec->op_time = ddi_get_time();
479 	rec->guid = zp->z_zfsvfs->z_os->os_dsl_dataset->ds_phys->ds_guid;
480 	ZEV_FILL_INODE_INFO(file, zp);
481 	zev_queue_message(op, msg);
482 }
483 
484 rz_zev_callbacks_t zev_callbacks = {
485 	/* zfsvfs events */
486 	.rz_zev_zfs_mount                = zev_zfs_mount_cb,
487 	.rz_zev_zfs_umount               = zev_zfs_umount_cb,
488 
489 	/* zvol zil events */
490 	.rz_zev_zvol_truncate            = zev_zvol_truncate_cb,
491 	.rz_zev_zvol_write               = zev_zvol_write_cb,
492 
493 	/* znode zil events */
494 	.rz_zev_znode_close_after_update = zev_znode_close_after_update_cb,
495 	.rz_zev_znode_create             = zev_znode_create_cb,
496 	.rz_zev_znode_remove             = zev_znode_remove_cb,
497 	.rz_zev_znode_link               = zev_znode_link_cb,
498 	.rz_zev_znode_symlink            = zev_znode_symlink_cb,
499 	.rz_zev_znode_rename             = zev_znode_rename_cb,
500 	.rz_zev_znode_write              = zev_znode_write_cb,
501 	.rz_zev_znode_truncate           = zev_znode_truncate_cb,
502 	.rz_zev_znode_setattr            = zev_znode_setattr_cb,
503 	.rz_zev_znode_acl                = zev_znode_acl_cb,
504 };
505 
506