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