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