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