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