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_MAXSTRLEN 4096 7 8 #define ZEV_ESCAPE(op, varname) \ 9 char escaped_##varname[ZEV_MAXSTRLEN]; \ 10 if ((zev_escape(varname, escaped_##varname)) != 0) { \ 11 zev_mq_printf(op, 1, "ERROR: ZEV_ESCAPE failed\n"); \ 12 return; \ 13 } 14 15 16 static int 17 zev_escape(char *from, char *to) 18 { 19 char *f = from; 20 char *t = to; 21 while (*f) { 22 switch (*f) { 23 case '\\': 24 *t = '\\'; t++; 25 *t = '\\'; t++; 26 break; 27 case '\'': 28 *t = '\\'; t++; 29 *t = '\''; t++; 30 break; 31 case '\n': 32 *t = '\\'; t++; 33 *t = 'n'; t++; 34 break; 35 default: 36 *t = *f; 37 t++; 38 } 39 f++; 40 if (*f && (t >= (to + ZEV_MAXSTRLEN - 2))) { 41 *t = '\0'; 42 return (ENAMETOOLONG); 43 } 44 } 45 *t = '\0'; 46 return (0); 47 } 48 49 void 50 zev_zfs_mount_cb(vfs_t *vfs, vnode_t *mpt, char *dataset, boolean_t remount) 51 { 52 if (zev_skip_pool(((zfsvfs_t *)vfs->vfs_data)->z_os)) 53 return; 54 /* we're watching this pool */ 55 ZEV_ESCAPE(ZEV_OP_ZFS_MOUNT, dataset); 56 char mountpoint[MAXPATHLEN+1]; 57 /* expensive, but we don't have many mount ops. */ 58 if ((vnodetopath(NULL, mpt, mountpoint, sizeof(mountpoint), 59 kcred)) != 0) { 60 zev_mq_printf(ZEV_OP_ZFS_MOUNT, 1, 61 "ERROR: ZEV_MOUNT: unresolvable mountpoint\n"); 62 return; 63 } 64 ZEV_ESCAPE(ZEV_OP_ZFS_MOUNT, mountpoint); 65 zev_mq_printf(ZEV_OP_ZFS_MOUNT, 0, 66 "ZFS_MOUNT fsid=%d:%d dataset='%s' remount=%s " 67 "mountpoint='%s'\n", 68 vfs->vfs_fsid.val[0], 69 vfs->vfs_fsid.val[1], 70 escaped_dataset, 71 remount == B_TRUE ? "true" : "false", 72 escaped_mountpoint); 73 } 74 75 void 76 zev_zfs_umount_cb(vfs_t *vfs) 77 { 78 if (zev_skip_pool(((zfsvfs_t *)vfs->vfs_data)->z_os)) 79 return; 80 zev_mq_printf(ZEV_OP_ZFS_UMOUNT, 0, "ZFS_UMOUNT fsid=%d:%d\n", 81 vfs->vfs_fsid.val[0], 82 vfs->vfs_fsid.val[1]); 83 } 84 85 void 86 zev_zvol_truncate_cb(char *dataset, objset_t *os, uint64_t off, uint64_t len) 87 { 88 if (zev_skip_pool(os)) 89 return; 90 ZEV_ESCAPE(ZEV_OP_ZVOL_TRUNCATE, dataset); 91 zev_mq_printf(ZEV_OP_ZVOL_TRUNCATE, 0, 92 "ZVOL_TRUNCATE dataset='%s' offset=%d len=%d\n", 93 escaped_dataset, 94 off, 95 len); 96 } 97 98 void 99 zev_zvol_write_cb(char *dataset, objset_t *os, uint64_t off, uint64_t len) 100 { 101 if (zev_skip_pool(os)) 102 return; 103 ZEV_ESCAPE(ZEV_OP_ZVOL_WRITE, dataset); 104 zev_mq_printf(ZEV_OP_ZVOL_WRITE, 0, 105 "ZVOL_WRITE dataset='%s' offset=%d len=%d\n", 106 escaped_dataset, 107 off, 108 len); 109 } 110 111 void 112 zev_znode_close_after_update_cb(znode_t *zp) 113 { 114 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 115 return; 116 zev_mq_printf(ZEV_OP_ZNODE_CLOSE_AFTER_UPDATE, 0, 117 "ZNODE_CLOSE_AFTER_UPDATE fsid=%d:%d inode=%d\n", 118 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 119 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 120 zp->z_id); 121 } 122 123 void 124 zev_znode_create_cb(znode_t *dzp, znode_t *zp, char *name, uint64_t txtype) 125 { 126 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 127 return; 128 ZEV_ESCAPE(ZEV_OP_ZNODE_CREATE, name); 129 char *op = NULL; 130 int type = (int)txtype; 131 switch(type) { 132 case TX_CREATE: 133 case TX_CREATE_ACL: 134 case TX_CREATE_ATTR: 135 case TX_CREATE_ACL_ATTR: 136 op = "ZNODE_CREATE"; 137 break; 138 case TX_MKDIR: 139 case TX_MKDIR_ACL: 140 case TX_MKDIR_ATTR: 141 case TX_MKDIR_ACL_ATTR: 142 op = "ZNODE_MKDIR"; 143 break; 144 case TX_MKXATTR: 145 op = "ZNODE_MAKE_XATTR_DIR"; 146 break; 147 default: 148 zev_mq_printf(ZEV_OP_ZNODE_CREATE, 1, 149 "ERROR: ZNODE_CREATE: unknown txtype %d " 150 "(dir_inode=%d inode=%d name='%s')\n", 151 type, 152 dzp->z_id, 153 zp->z_id, 154 escaped_name); 155 return; 156 } 157 zev_mq_printf(ZEV_OP_ZNODE_CREATE, 0, 158 "%s fsid=%d:%d dir_inode=%d inode=%d name='%s'\n", 159 op, 160 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 161 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 162 dzp->z_id, 163 zp->z_id, 164 escaped_name); 165 } 166 167 void 168 zev_znode_remove_cb(znode_t *dzp, char *name, uint64_t txtype) 169 { 170 if (zev_skip_pool(dzp->z_zfsvfs->z_os)) 171 return; 172 ZEV_ESCAPE(ZEV_OP_ZNODE_REMOVE, name); 173 char *op = NULL; 174 int type = (int)txtype; 175 switch(type) { 176 case TX_REMOVE: 177 op = "ZNODE_REMOVE"; 178 break; 179 case TX_RMDIR: 180 op = "ZNODE_RMDIR"; 181 break; 182 default: 183 zev_mq_printf(ZEV_OP_ZNODE_REMOVE, 1, 184 "ERROR: ZNODE_REMOVE: unknown txtype %d " 185 "(dir_inode=%d name='%s')\n", 186 type, 187 dzp->z_id, 188 escaped_name); 189 return; 190 } 191 zev_mq_printf(ZEV_OP_ZNODE_REMOVE, 0, 192 "%s fsid=%d:%d dir_inode=%d name='%s'\n", 193 op, 194 dzp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 195 dzp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 196 dzp->z_id, 197 escaped_name); 198 } 199 200 void 201 zev_znode_link_cb(znode_t *dzp, znode_t *zp, char *name) 202 { 203 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 204 return; 205 ZEV_ESCAPE(ZEV_OP_ZNODE_LINK, name); 206 zev_mq_printf(ZEV_OP_ZNODE_LINK, 0, 207 "ZNODE_LINK fsid=%d:%d dir_inode=%d inode=%d name='%s'\n", 208 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 209 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 210 dzp->z_id, 211 zp->z_id, 212 escaped_name); 213 } 214 215 void 216 zev_znode_symlink_cb(znode_t *dzp, znode_t *zp, char *name, char *link) 217 { 218 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 219 return; 220 ZEV_ESCAPE(ZEV_OP_ZNODE_SYMLINK, name); 221 ZEV_ESCAPE(ZEV_OP_ZNODE_SYMLINK, link); 222 zev_mq_printf(ZEV_OP_ZNODE_SYMLINK, 0, 223 "ZNODE_SYMLINK fsid=%d:%d dir_inode=%d inode=%d " 224 "name='%s' link='%s'\n", 225 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 226 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 227 dzp->z_id, 228 zp->z_id, 229 escaped_name, 230 escaped_link); 231 } 232 233 void 234 zev_znode_rename_cb(znode_t *sdzp, char *sname, znode_t *tdzp, 235 char *tname, znode_t *szp) 236 { 237 if (zev_skip_pool(szp->z_zfsvfs->z_os)) 238 return; 239 ZEV_ESCAPE(ZEV_OP_ZNODE_RENAME, sname); 240 ZEV_ESCAPE(ZEV_OP_ZNODE_RENAME, tname); 241 zev_mq_printf(ZEV_OP_ZNODE_RENAME, 0, 242 "ZNODE_RENAME fsid=%d:%d src_dir_inode=%d src_name='%s' " 243 "target_dir_inode=%d target_name='%s' inode=%d\n", 244 szp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 245 szp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 246 sdzp->z_id, 247 escaped_sname, 248 tdzp->z_id, 249 escaped_tname, 250 szp->z_id); 251 } 252 253 void 254 zev_znode_write_cb(znode_t *zp, uint64_t off, uint64_t len) 255 { 256 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 257 return; 258 zev_mq_printf(ZEV_OP_ZNODE_WRITE, 0, 259 "ZNODE_WRITE fsid=%d:%d inode=%d offset=%d len=%d\n", 260 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 261 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 262 zp->z_id, 263 off, 264 len); 265 } 266 267 void 268 zev_znode_truncate_cb(znode_t *zp, uint64_t off, uint64_t len) 269 { 270 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 271 return; 272 zev_mq_printf(ZEV_OP_ZNODE_TRUNCATE, 0, 273 "ZNODE_TRUNCATE fsid=%d:%d inode=%d offset=%d len=%d\n", 274 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 275 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 276 zp->z_id, 277 off, 278 len); 279 } 280 281 void 282 zev_znode_setattr_cb(znode_t *zp) 283 { 284 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 285 return; 286 zev_mq_printf(ZEV_OP_ZNODE_SETATTR, 0, 287 "ZNODE_SETATTR fsid=%d:%d inode=%d\n", 288 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 289 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 290 zp->z_id); 291 } 292 293 void 294 zev_znode_acl_cb(znode_t *zp) 295 { 296 if (zev_skip_pool(zp->z_zfsvfs->z_os)) 297 return; 298 zev_mq_printf(ZEV_OP_ZNODE_ACL, 0, 299 "ZNODE_ACL fsid=%d:%d inode=%d\n", 300 zp->z_zfsvfs->z_vfs->vfs_fsid.val[0], 301 zp->z_zfsvfs->z_vfs->vfs_fsid.val[1], 302 zp->z_id); 303 } 304 305 rz_zev_callbacks_t zev_callbacks = { 306 /* zfsvfs events */ 307 .rz_zev_zfs_mount = zev_zfs_mount_cb, 308 .rz_zev_zfs_umount = zev_zfs_umount_cb, 309 310 /* zvol zil events */ 311 .rz_zev_zvol_truncate = zev_zvol_truncate_cb, 312 .rz_zev_zvol_write = zev_zvol_write_cb, 313 314 /* znode zil events */ 315 .rz_zev_znode_close_after_update = zev_znode_close_after_update_cb, 316 .rz_zev_znode_create = zev_znode_create_cb, 317 .rz_zev_znode_remove = zev_znode_remove_cb, 318 .rz_zev_znode_link = zev_znode_link_cb, 319 .rz_zev_znode_symlink = zev_znode_symlink_cb, 320 .rz_zev_znode_rename = zev_znode_rename_cb, 321 .rz_zev_znode_write = zev_znode_write_cb, 322 .rz_zev_znode_truncate = zev_znode_truncate_cb, 323 .rz_zev_znode_setattr = zev_znode_setattr_cb, 324 .rz_zev_znode_acl = zev_znode_acl_cb, 325 }; 326 327