#include #include #include #include #define ZEV_MAXSTRLEN 4096 #define ZEV_ESCAPE(op, varname) \ char escaped_##varname[ZEV_MAXSTRLEN]; \ if ((zev_escape(varname, escaped_##varname)) != 0) { \ zev_mq_printf(op, 1, "ERROR: ZEV_ESCAPE failed\n"); \ return; \ } static int zev_escape(char *from, char *to) { char *f = from; char *t = to; while (*f) { switch (*f) { case '\\': *t = '\\'; t++; *t = '\\'; t++; break; case '\'': *t = '\\'; t++; *t = '\''; t++; break; case '\n': *t = '\\'; t++; *t = 'n'; t++; break; default: *t = *f; t++; } f++; if (*f && (t >= (to + ZEV_MAXSTRLEN - 2))) { *t = '\0'; return (ENAMETOOLONG); } } *t = '\0'; return (0); } void zev_zfs_mount_cb(vfs_t *vfs, vnode_t *mpt, char *dataset, boolean_t remount) { if (zev_skip_pool(((zfsvfs_t *)vfs->vfs_data)->z_os)) return; /* we're watching this pool */ ZEV_ESCAPE(ZEV_OP_ZFS_MOUNT, dataset); char mountpoint[MAXPATHLEN+1]; /* expensive, but we don't have many mount ops. */ if ((vnodetopath(NULL, mpt, mountpoint, sizeof(mountpoint), kcred)) != 0) { zev_mq_printf(ZEV_OP_ZFS_MOUNT, 1, "ERROR: ZEV_MOUNT: unresolvable mountpoint\n"); return; } ZEV_ESCAPE(ZEV_OP_ZFS_MOUNT, mountpoint); zev_mq_printf(ZEV_OP_ZFS_MOUNT, 0, "ZFS_MOUNT fsid=%d:%d dataset='%s' remount=%s " "mountpoint='%s'\n", vfs->vfs_fsid.val[0], vfs->vfs_fsid.val[1], escaped_dataset, remount == B_TRUE ? "true" : "false", escaped_mountpoint); } void zev_zfs_umount_cb(vfs_t *vfs) { if (zev_skip_pool(((zfsvfs_t *)vfs->vfs_data)->z_os)) return; zev_mq_printf(ZEV_OP_ZFS_UMOUNT, 0, "ZFS_UMOUNT fsid=%d:%d\n", vfs->vfs_fsid.val[0], vfs->vfs_fsid.val[1]); } void zev_zvol_truncate_cb(char *dataset, objset_t *os, uint64_t off, uint64_t len) { if (zev_skip_pool(os)) return; ZEV_ESCAPE(ZEV_OP_ZVOL_TRUNCATE, dataset); zev_mq_printf(ZEV_OP_ZVOL_TRUNCATE, 0, "ZVOL_TRUNCATE dataset='%s' offset=%d len=%d\n", escaped_dataset, off, len); } void zev_zvol_write_cb(char *dataset, objset_t *os, uint64_t off, uint64_t len) { if (zev_skip_pool(os)) return; ZEV_ESCAPE(ZEV_OP_ZVOL_WRITE, dataset); zev_mq_printf(ZEV_OP_ZVOL_WRITE, 0, "ZVOL_WRITE dataset='%s' offset=%d len=%d\n", escaped_dataset, off, len); } void zev_znode_close_after_update_cb(znode_t *zp) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; zev_mq_printf(ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE, 0, "ZNODE_CLOSE_AFTER_UPDATE fsid=%d:%d inode=%d\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], zp->z_id); } void zev_znode_create_cb(znode_t *dzp, znode_t *zp, char *name, uint64_t txtype) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; ZEV_ESCAPE(ZEV_OP_ZNODE_CREATE, name); char *op = NULL; int type = (int)txtype; switch(type) { case TX_CREATE: case TX_CREATE_ACL: case TX_CREATE_ATTR: case TX_CREATE_ACL_ATTR: op = "ZNODE_CREATE"; break; case TX_MKDIR: case TX_MKDIR_ACL: case TX_MKDIR_ATTR: case TX_MKDIR_ACL_ATTR: op = "ZNODE_MKDIR"; break; case TX_MKXATTR: op = "ZNODE_MAKE_XATTR_DIR"; break; default: zev_mq_printf(ZEV_OP_ZNODE_CREATE, 1, "ERROR: ZNODE_CREATE: unknown txtype %d " "(dir_inode=%d inode=%d name='%s')\n", type, dzp->z_id, zp->z_id, escaped_name); return; } zev_mq_printf(ZEV_OP_ZNODE_CREATE, 0, "%s fsid=%d:%d dir_inode=%d inode=%d name='%s'\n", op, zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], dzp->z_id, zp->z_id, escaped_name); } void zev_znode_remove_cb(znode_t *dzp, char *name, uint64_t txtype) { if (zev_skip_pool(dzp->z_zfsvfs->z_os)) return; ZEV_ESCAPE(ZEV_OP_ZNODE_REMOVE, name); char *op = NULL; int type = (int)txtype; switch(type) { case TX_REMOVE: op = "ZNODE_REMOVE"; break; case TX_RMDIR: op = "ZNODE_RMDIR"; break; default: zev_mq_printf(ZEV_OP_ZNODE_REMOVE, 1, "ERROR: ZNODE_REMOVE: unknown txtype %d " "(dir_inode=%d name='%s')\n", type, dzp->z_id, escaped_name); return; } zev_mq_printf(ZEV_OP_ZNODE_REMOVE, 0, "%s fsid=%d:%d dir_inode=%d name='%s'\n", op, dzp->z_zfsvfs->z_vfs->vfs_fsid.val[0], dzp->z_zfsvfs->z_vfs->vfs_fsid.val[1], dzp->z_id, escaped_name); } void zev_znode_link_cb(znode_t *dzp, znode_t *zp, char *name) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; ZEV_ESCAPE(ZEV_OP_ZNODE_LINK, name); zev_mq_printf(ZEV_OP_ZNODE_LINK, 0, "ZNODE_LINK fsid=%d:%d dir_inode=%d inode=%d name='%s'\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], dzp->z_id, zp->z_id, escaped_name); } void zev_znode_symlink_cb(znode_t *dzp, znode_t *zp, char *name, char *link) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; ZEV_ESCAPE(ZEV_OP_ZNODE_SYMLINK, name); ZEV_ESCAPE(ZEV_OP_ZNODE_SYMLINK, link); zev_mq_printf(ZEV_OP_ZNODE_SYMLINK, 0, "ZNODE_SYMLINK fsid=%d:%d dir_inode=%d inode=%d " "name='%s' link='%s'\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], dzp->z_id, zp->z_id, escaped_name, escaped_link); } void zev_znode_rename_cb(znode_t *sdzp, char *sname, znode_t *tdzp, char *tname, znode_t *szp) { if (zev_skip_pool(szp->z_zfsvfs->z_os)) return; ZEV_ESCAPE(ZEV_OP_ZNODE_RENAME, sname); ZEV_ESCAPE(ZEV_OP_ZNODE_RENAME, tname); zev_mq_printf(ZEV_OP_ZNODE_RENAME, 0, "ZNODE_RENAME fsid=%d:%d src_dir_inode=%d src_name='%s' " "target_dir_inode=%d target_name='%s' inode=%d\n", szp->z_zfsvfs->z_vfs->vfs_fsid.val[0], szp->z_zfsvfs->z_vfs->vfs_fsid.val[1], sdzp->z_id, escaped_sname, tdzp->z_id, escaped_tname, szp->z_id); } void zev_znode_write_cb(znode_t *zp, uint64_t off, uint64_t len) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; zev_mq_printf(ZEV_OP_ZNODE_WRITE, 0, "ZNODE_WRITE fsid=%d:%d inode=%d offset=%d len=%d\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], zp->z_id, off, len); } void zev_znode_truncate_cb(znode_t *zp, uint64_t off, uint64_t len) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; zev_mq_printf(ZEV_OP_ZNODE_TRUNCATE, 0, "ZNODE_TRUNCATE fsid=%d:%d inode=%d offset=%d len=%d\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], zp->z_id, off, len); } void zev_znode_setattr_cb(znode_t *zp) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; zev_mq_printf(ZEV_OP_ZNODE_SETATTR, 0, "ZNODE_SETATTR fsid=%d:%d inode=%d\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], zp->z_id); } void zev_znode_acl_cb(znode_t *zp) { if (zev_skip_pool(zp->z_zfsvfs->z_os)) return; zev_mq_printf(ZEV_OP_ZNODE_ACL, 0, "ZNODE_ACL fsid=%d:%d inode=%d\n", zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], zp->z_id); } rz_zev_callbacks_t zev_callbacks = { /* zfsvfs events */ .rz_zev_zfs_mount = zev_zfs_mount_cb, .rz_zev_zfs_umount = zev_zfs_umount_cb, /* zvol zil events */ .rz_zev_zvol_truncate = zev_zvol_truncate_cb, .rz_zev_zvol_write = zev_zvol_write_cb, /* znode zil events */ .rz_zev_znode_close_after_update = zev_znode_close_after_update_cb, .rz_zev_znode_create = zev_znode_create_cb, .rz_zev_znode_remove = zev_znode_remove_cb, .rz_zev_znode_link = zev_znode_link_cb, .rz_zev_znode_symlink = zev_znode_symlink_cb, .rz_zev_znode_rename = zev_znode_rename_cb, .rz_zev_znode_write = zev_znode_write_cb, .rz_zev_znode_truncate = zev_znode_truncate_cb, .rz_zev_znode_setattr = zev_znode_setattr_cb, .rz_zev_znode_acl = zev_znode_acl_cb, };