1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5104e2ed7Sperrin * Common Development and Distribution License (the "License"). 6104e2ed7Sperrin * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 225002558fSNeil Perrin * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 239a686fbcSPaul Dagnelie * Copyright (c) 2015 by Delphix. All rights reserved. 24c3d26abcSMatthew Ahrens * Copyright (c) 2014 Integros [integros.com] 25fa9e4066Sahrens */ 26fa9e4066Sahrens 27fa9e4066Sahrens #include <sys/types.h> 28fa9e4066Sahrens #include <sys/param.h> 29fa9e4066Sahrens #include <sys/systm.h> 30fa9e4066Sahrens #include <sys/sysmacros.h> 31fa9e4066Sahrens #include <sys/cmn_err.h> 32fa9e4066Sahrens #include <sys/kmem.h> 33fa9e4066Sahrens #include <sys/thread.h> 34fa9e4066Sahrens #include <sys/file.h> 35fa9e4066Sahrens #include <sys/vfs.h> 36fa9e4066Sahrens #include <sys/zfs_znode.h> 37fa9e4066Sahrens #include <sys/zfs_dir.h> 38fa9e4066Sahrens #include <sys/zil.h> 396ce0521aSperrin #include <sys/zil_impl.h> 40fa9e4066Sahrens #include <sys/byteorder.h> 41fa9e4066Sahrens #include <sys/policy.h> 42fa9e4066Sahrens #include <sys/stat.h> 43fa9e4066Sahrens #include <sys/mode.h> 44fa9e4066Sahrens #include <sys/acl.h> 45fa9e4066Sahrens #include <sys/dmu.h> 46fa9e4066Sahrens #include <sys/spa.h> 47da6c28aaSamw #include <sys/zfs_fuid.h> 48fa9e4066Sahrens #include <sys/ddi.h> 491209a471SNeil Perrin #include <sys/dsl_dataset.h> 50d78b796cSAndreas Jaekel #include <sys/zfs_events.h> 511209a471SNeil Perrin 52fa9e4066Sahrens /* 531209a471SNeil Perrin * These zfs_log_* functions must be called within a dmu tx, in one 541209a471SNeil Perrin * of 2 contexts depending on zilog->z_replay: 551209a471SNeil Perrin * 561209a471SNeil Perrin * Non replay mode 571209a471SNeil Perrin * --------------- 581209a471SNeil Perrin * We need to record the transaction so that if it is committed to 591209a471SNeil Perrin * the Intent Log then it can be replayed. An intent log transaction 601209a471SNeil Perrin * structure (itx_t) is allocated and all the information necessary to 611209a471SNeil Perrin * possibly replay the transaction is saved in it. The itx is then assigned 621209a471SNeil Perrin * a sequence number and inserted in the in-memory list anchored in the zilog. 631209a471SNeil Perrin * 641209a471SNeil Perrin * Replay mode 651209a471SNeil Perrin * ----------- 661209a471SNeil Perrin * We need to mark the intent log record as replayed in the log header. 671209a471SNeil Perrin * This is done in the same transaction as the replay so that they 681209a471SNeil Perrin * commit atomically. 69fa9e4066Sahrens */ 70fa9e4066Sahrens 71da6c28aaSamw int 72da6c28aaSamw zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap) 73da6c28aaSamw { 74da6c28aaSamw int isxvattr = (vap->va_mask & AT_XVATTR); 75da6c28aaSamw switch (type) { 76da6c28aaSamw case Z_FILE: 77da6c28aaSamw if (vsecp == NULL && !isxvattr) 78da6c28aaSamw return (TX_CREATE); 79da6c28aaSamw if (vsecp && isxvattr) 80da6c28aaSamw return (TX_CREATE_ACL_ATTR); 81da6c28aaSamw if (vsecp) 82da6c28aaSamw return (TX_CREATE_ACL); 83da6c28aaSamw else 84da6c28aaSamw return (TX_CREATE_ATTR); 85da6c28aaSamw /*NOTREACHED*/ 86da6c28aaSamw case Z_DIR: 87da6c28aaSamw if (vsecp == NULL && !isxvattr) 88da6c28aaSamw return (TX_MKDIR); 89da6c28aaSamw if (vsecp && isxvattr) 90da6c28aaSamw return (TX_MKDIR_ACL_ATTR); 91da6c28aaSamw if (vsecp) 92da6c28aaSamw return (TX_MKDIR_ACL); 93da6c28aaSamw else 94da6c28aaSamw return (TX_MKDIR_ATTR); 95da6c28aaSamw case Z_XATTRDIR: 96da6c28aaSamw return (TX_MKXATTR); 97da6c28aaSamw } 98da6c28aaSamw ASSERT(0); 99da6c28aaSamw return (TX_MAX_TYPE); 100da6c28aaSamw } 101da6c28aaSamw 102fa9e4066Sahrens /* 103da6c28aaSamw * build up the log data necessary for logging xvattr_t 104da6c28aaSamw * First lr_attr_t is initialized. following the lr_attr_t 105da6c28aaSamw * is the mapsize and attribute bitmap copied from the xvattr_t. 106da6c28aaSamw * Following the bitmap and bitmapsize two 64 bit words are reserved 107da6c28aaSamw * for the create time which may be set. Following the create time 108da6c28aaSamw * records a single 64 bit integer which has the bits to set on 109da6c28aaSamw * replay for the xvattr. 110da6c28aaSamw */ 111da6c28aaSamw static void 112da6c28aaSamw zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 113da6c28aaSamw { 114da6c28aaSamw uint32_t *bitmap; 115da6c28aaSamw uint64_t *attrs; 116da6c28aaSamw uint64_t *crtime; 117da6c28aaSamw xoptattr_t *xoap; 118da6c28aaSamw void *scanstamp; 119da6c28aaSamw int i; 120da6c28aaSamw 121da6c28aaSamw xoap = xva_getxoptattr(xvap); 122da6c28aaSamw ASSERT(xoap); 123da6c28aaSamw 124da6c28aaSamw lrattr->lr_attr_masksize = xvap->xva_mapsize; 125da6c28aaSamw bitmap = &lrattr->lr_attr_bitmap; 126da6c28aaSamw for (i = 0; i != xvap->xva_mapsize; i++, bitmap++) { 127da6c28aaSamw *bitmap = xvap->xva_reqattrmap[i]; 128da6c28aaSamw } 129da6c28aaSamw 130da6c28aaSamw /* Now pack the attributes up in a single uint64_t */ 131da6c28aaSamw attrs = (uint64_t *)bitmap; 132da6c28aaSamw crtime = attrs + 1; 133da6c28aaSamw scanstamp = (caddr_t)(crtime + 2); 134da6c28aaSamw *attrs = 0; 135da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_READONLY)) 136da6c28aaSamw *attrs |= (xoap->xoa_readonly == 0) ? 0 : 137da6c28aaSamw XAT0_READONLY; 138da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) 139da6c28aaSamw *attrs |= (xoap->xoa_hidden == 0) ? 0 : 140da6c28aaSamw XAT0_HIDDEN; 141da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) 142da6c28aaSamw *attrs |= (xoap->xoa_system == 0) ? 0 : 143da6c28aaSamw XAT0_SYSTEM; 144da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) 145da6c28aaSamw *attrs |= (xoap->xoa_archive == 0) ? 0 : 146da6c28aaSamw XAT0_ARCHIVE; 147da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) 148da6c28aaSamw *attrs |= (xoap->xoa_immutable == 0) ? 0 : 149da6c28aaSamw XAT0_IMMUTABLE; 150da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) 151da6c28aaSamw *attrs |= (xoap->xoa_nounlink == 0) ? 0 : 152da6c28aaSamw XAT0_NOUNLINK; 153da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) 154da6c28aaSamw *attrs |= (xoap->xoa_appendonly == 0) ? 0 : 155da6c28aaSamw XAT0_APPENDONLY; 156da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) 157da6c28aaSamw *attrs |= (xoap->xoa_opaque == 0) ? 0 : 158da6c28aaSamw XAT0_APPENDONLY; 159da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) 160da6c28aaSamw *attrs |= (xoap->xoa_nodump == 0) ? 0 : 161da6c28aaSamw XAT0_NODUMP; 162da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) 163da6c28aaSamw *attrs |= (xoap->xoa_av_quarantined == 0) ? 0 : 164da6c28aaSamw XAT0_AV_QUARANTINED; 165da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) 166da6c28aaSamw *attrs |= (xoap->xoa_av_modified == 0) ? 0 : 167da6c28aaSamw XAT0_AV_MODIFIED; 168da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) 169da6c28aaSamw ZFS_TIME_ENCODE(&xoap->xoa_createtime, crtime); 170da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) 171da6c28aaSamw bcopy(xoap->xoa_av_scanstamp, scanstamp, AV_SCANSTAMP_SZ); 1727a286c47SDai Ngo if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) 1737a286c47SDai Ngo *attrs |= (xoap->xoa_reparse == 0) ? 0 : 1747a286c47SDai Ngo XAT0_REPARSE; 175fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) 176fd9ee8b5Sjoyce mcintosh *attrs |= (xoap->xoa_offline == 0) ? 0 : 177fd9ee8b5Sjoyce mcintosh XAT0_OFFLINE; 178fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) 179fd9ee8b5Sjoyce mcintosh *attrs |= (xoap->xoa_sparse == 0) ? 0 : 180fd9ee8b5Sjoyce mcintosh XAT0_SPARSE; 181da6c28aaSamw } 182da6c28aaSamw 183da6c28aaSamw static void * 184da6c28aaSamw zfs_log_fuid_ids(zfs_fuid_info_t *fuidp, void *start) 185da6c28aaSamw { 186da6c28aaSamw zfs_fuid_t *zfuid; 187da6c28aaSamw uint64_t *fuidloc = start; 188da6c28aaSamw 189da6c28aaSamw /* First copy in the ACE FUIDs */ 190da6c28aaSamw for (zfuid = list_head(&fuidp->z_fuids); zfuid; 191da6c28aaSamw zfuid = list_next(&fuidp->z_fuids, zfuid)) { 192da6c28aaSamw *fuidloc++ = zfuid->z_logfuid; 193da6c28aaSamw } 194da6c28aaSamw return (fuidloc); 195da6c28aaSamw } 196da6c28aaSamw 197da6c28aaSamw 198da6c28aaSamw static void * 199da6c28aaSamw zfs_log_fuid_domains(zfs_fuid_info_t *fuidp, void *start) 200da6c28aaSamw { 201da6c28aaSamw zfs_fuid_domain_t *zdomain; 202da6c28aaSamw 203da6c28aaSamw /* now copy in the domain info, if any */ 204da6c28aaSamw if (fuidp->z_domain_str_sz != 0) { 205da6c28aaSamw for (zdomain = list_head(&fuidp->z_domains); zdomain; 206da6c28aaSamw zdomain = list_next(&fuidp->z_domains, zdomain)) { 207da6c28aaSamw bcopy((void *)zdomain->z_domain, start, 208da6c28aaSamw strlen(zdomain->z_domain) + 1); 209da6c28aaSamw start = (caddr_t)start + 210da6c28aaSamw strlen(zdomain->z_domain) + 1; 211da6c28aaSamw } 212da6c28aaSamw } 213da6c28aaSamw return (start); 214da6c28aaSamw } 215da6c28aaSamw 216da6c28aaSamw /* 217f7170741SWill Andrews * Handles TX_CREATE, TX_CREATE_ATTR, TX_MKDIR, TX_MKDIR_ATTR and 218f7170741SWill Andrews * TK_MKXATTR transactions. 219da6c28aaSamw * 220da6c28aaSamw * TX_CREATE and TX_MKDIR are standard creates, but they may have FUID 221da6c28aaSamw * domain information appended prior to the name. In this case the 222da6c28aaSamw * uid/gid in the log record will be a log centric FUID. 223da6c28aaSamw * 224da6c28aaSamw * TX_CREATE_ACL_ATTR and TX_MKDIR_ACL_ATTR handle special creates that 225da6c28aaSamw * may contain attributes, ACL and optional fuid information. 226da6c28aaSamw * 227da6c28aaSamw * TX_CREATE_ACL and TX_MKDIR_ACL handle special creates that specify 228da6c28aaSamw * and ACL and normal users/groups in the ACEs. 229da6c28aaSamw * 230da6c28aaSamw * There may be an optional xvattr attribute information similar 231da6c28aaSamw * to zfs_log_setattr. 232da6c28aaSamw * 233da6c28aaSamw * Also, after the file name "domain" strings may be appended. 234fa9e4066Sahrens */ 235b19a79ecSperrin void 236da6c28aaSamw zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 237da6c28aaSamw znode_t *dzp, znode_t *zp, char *name, vsecattr_t *vsecp, 238da6c28aaSamw zfs_fuid_info_t *fuidp, vattr_t *vap) 239fa9e4066Sahrens { 240fa9e4066Sahrens itx_t *itx; 241fa9e4066Sahrens lr_create_t *lr; 242da6c28aaSamw lr_acl_create_t *lracl; 243d5285caeSGeorge Wilson size_t aclsize = (vsecp != NULL) ? vsecp->vsa_aclentsz : 0; 244da6c28aaSamw size_t xvatsize = 0; 245da6c28aaSamw size_t txsize; 246da6c28aaSamw xvattr_t *xvap = (xvattr_t *)vap; 247da6c28aaSamw void *end; 248da6c28aaSamw size_t lrsize; 249fa9e4066Sahrens size_t namesize = strlen(name) + 1; 250da6c28aaSamw size_t fuidsz = 0; 251fa9e4066Sahrens 252b24ab676SJeff Bonwick if (zil_replaying(zilog, tx)) 253b19a79ecSperrin return; 254fa9e4066Sahrens 255da6c28aaSamw /* 256da6c28aaSamw * If we have FUIDs present then add in space for 257da6c28aaSamw * domains and ACE fuid's if any. 258da6c28aaSamw */ 259da6c28aaSamw if (fuidp) { 260da6c28aaSamw fuidsz += fuidp->z_domain_str_sz; 261da6c28aaSamw fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t); 262da6c28aaSamw } 263da6c28aaSamw 264da6c28aaSamw if (vap->va_mask & AT_XVATTR) 265da6c28aaSamw xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize); 266da6c28aaSamw 267da6c28aaSamw if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR || 268da6c28aaSamw (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR || 269da6c28aaSamw (int)txtype == TX_MKXATTR) { 270da6c28aaSamw txsize = sizeof (*lr) + namesize + fuidsz + xvatsize; 271da6c28aaSamw lrsize = sizeof (*lr); 272da6c28aaSamw } else { 273da6c28aaSamw txsize = 274da6c28aaSamw sizeof (lr_acl_create_t) + namesize + fuidsz + 275569e6c63Smarks ZIL_ACE_LENGTH(aclsize) + xvatsize; 276da6c28aaSamw lrsize = sizeof (lr_acl_create_t); 277da6c28aaSamw } 278da6c28aaSamw 279da6c28aaSamw itx = zil_itx_create(txtype, txsize); 280da6c28aaSamw 281fa9e4066Sahrens lr = (lr_create_t *)&itx->itx_lr; 282fa9e4066Sahrens lr->lr_doid = dzp->z_id; 283fa9e4066Sahrens lr->lr_foid = zp->z_id; 2840a586ceaSMark Shellenbaum lr->lr_mode = zp->z_mode; 2850a586ceaSMark Shellenbaum if (!IS_EPHEMERAL(zp->z_uid)) { 2860a586ceaSMark Shellenbaum lr->lr_uid = (uint64_t)zp->z_uid; 287da6c28aaSamw } else { 288da6c28aaSamw lr->lr_uid = fuidp->z_fuid_owner; 289da6c28aaSamw } 2900a586ceaSMark Shellenbaum if (!IS_EPHEMERAL(zp->z_gid)) { 2910a586ceaSMark Shellenbaum lr->lr_gid = (uint64_t)zp->z_gid; 292da6c28aaSamw } else { 293da6c28aaSamw lr->lr_gid = fuidp->z_fuid_group; 294da6c28aaSamw } 2950a586ceaSMark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zp->z_zfsvfs), &lr->lr_gen, 2960a586ceaSMark Shellenbaum sizeof (uint64_t)); 2970a586ceaSMark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs), 2980a586ceaSMark Shellenbaum lr->lr_crtime, sizeof (uint64_t) * 2); 2990a586ceaSMark Shellenbaum 3000a586ceaSMark Shellenbaum if (sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zp->z_zfsvfs), &lr->lr_rdev, 3010a586ceaSMark Shellenbaum sizeof (lr->lr_rdev)) != 0) 3020a586ceaSMark Shellenbaum lr->lr_rdev = 0; 303da6c28aaSamw 304da6c28aaSamw /* 305da6c28aaSamw * Fill in xvattr info if any 306da6c28aaSamw */ 307da6c28aaSamw if (vap->va_mask & AT_XVATTR) { 308da6c28aaSamw zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap); 309da6c28aaSamw end = (caddr_t)lr + lrsize + xvatsize; 310da6c28aaSamw } else { 311da6c28aaSamw end = (caddr_t)lr + lrsize; 312da6c28aaSamw } 313da6c28aaSamw 314da6c28aaSamw /* Now fill in any ACL info */ 315da6c28aaSamw 316da6c28aaSamw if (vsecp) { 317da6c28aaSamw lracl = (lr_acl_create_t *)&itx->itx_lr; 318da6c28aaSamw lracl->lr_aclcnt = vsecp->vsa_aclcnt; 319da6c28aaSamw lracl->lr_acl_bytes = aclsize; 320da6c28aaSamw lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0; 321da6c28aaSamw lracl->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0; 322da6c28aaSamw if (vsecp->vsa_aclflags & VSA_ACE_ACLFLAGS) 323da6c28aaSamw lracl->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags; 324da6c28aaSamw else 325da6c28aaSamw lracl->lr_acl_flags = 0; 326da6c28aaSamw 327da6c28aaSamw bcopy(vsecp->vsa_aclentp, end, aclsize); 328569e6c63Smarks end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize); 329da6c28aaSamw } 330da6c28aaSamw 331da6c28aaSamw /* drop in FUID info */ 332da6c28aaSamw if (fuidp) { 333da6c28aaSamw end = zfs_log_fuid_ids(fuidp, end); 334da6c28aaSamw end = zfs_log_fuid_domains(fuidp, end); 335da6c28aaSamw } 336da6c28aaSamw /* 337da6c28aaSamw * Now place file name in log record 338da6c28aaSamw */ 339da6c28aaSamw bcopy(name, end, namesize); 340fa9e4066Sahrens 3415002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 342d78b796cSAndreas Jaekel 343d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 344d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_create) 345e206ace3SAndreas Jaekel rz_zev_callbacks->rz_zev_znode_create(dzp, zp, tx, name, 346e206ace3SAndreas Jaekel txtype); 347d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 348fa9e4066Sahrens } 349fa9e4066Sahrens 350fa9e4066Sahrens /* 351f7170741SWill Andrews * Handles both TX_REMOVE and TX_RMDIR transactions. 352fa9e4066Sahrens */ 353b19a79ecSperrin void 354da6c28aaSamw zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 3555002558fSNeil Perrin znode_t *dzp, char *name, uint64_t foid) 356fa9e4066Sahrens { 357fa9e4066Sahrens itx_t *itx; 358fa9e4066Sahrens lr_remove_t *lr; 359fa9e4066Sahrens size_t namesize = strlen(name) + 1; 360fa9e4066Sahrens 361b24ab676SJeff Bonwick if (zil_replaying(zilog, tx)) 362b19a79ecSperrin return; 363fa9e4066Sahrens 364fa9e4066Sahrens itx = zil_itx_create(txtype, sizeof (*lr) + namesize); 365fa9e4066Sahrens lr = (lr_remove_t *)&itx->itx_lr; 366fa9e4066Sahrens lr->lr_doid = dzp->z_id; 367fa9e4066Sahrens bcopy(name, (char *)(lr + 1), namesize); 368fa9e4066Sahrens 36951bd2f97SNeil Perrin itx->itx_oid = foid; 3705002558fSNeil Perrin 3715002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 372fa9e4066Sahrens } 373fa9e4066Sahrens 374fa9e4066Sahrens /* 375f7170741SWill Andrews * Handles TX_LINK transactions. 376fa9e4066Sahrens */ 377b19a79ecSperrin void 378da6c28aaSamw zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 379fa9e4066Sahrens znode_t *dzp, znode_t *zp, char *name) 380fa9e4066Sahrens { 381fa9e4066Sahrens itx_t *itx; 382fa9e4066Sahrens lr_link_t *lr; 383fa9e4066Sahrens size_t namesize = strlen(name) + 1; 384fa9e4066Sahrens 385b24ab676SJeff Bonwick if (zil_replaying(zilog, tx)) 386b19a79ecSperrin return; 387fa9e4066Sahrens 388fa9e4066Sahrens itx = zil_itx_create(txtype, sizeof (*lr) + namesize); 389fa9e4066Sahrens lr = (lr_link_t *)&itx->itx_lr; 390fa9e4066Sahrens lr->lr_doid = dzp->z_id; 391fa9e4066Sahrens lr->lr_link_obj = zp->z_id; 392fa9e4066Sahrens bcopy(name, (char *)(lr + 1), namesize); 393fa9e4066Sahrens 3945002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 395d78b796cSAndreas Jaekel 396d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 397d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_link) 398e206ace3SAndreas Jaekel rz_zev_callbacks->rz_zev_znode_link(dzp, zp, tx, name); 399d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 400fa9e4066Sahrens } 401fa9e4066Sahrens 402fa9e4066Sahrens /* 403f7170741SWill Andrews * Handles TX_SYMLINK transactions. 404fa9e4066Sahrens */ 405b19a79ecSperrin void 406da6c28aaSamw zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 407fa9e4066Sahrens znode_t *dzp, znode_t *zp, char *name, char *link) 408fa9e4066Sahrens { 409fa9e4066Sahrens itx_t *itx; 410fa9e4066Sahrens lr_create_t *lr; 411fa9e4066Sahrens size_t namesize = strlen(name) + 1; 412fa9e4066Sahrens size_t linksize = strlen(link) + 1; 413fa9e4066Sahrens 414b24ab676SJeff Bonwick if (zil_replaying(zilog, tx)) 415b19a79ecSperrin return; 416fa9e4066Sahrens 417fa9e4066Sahrens itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize); 418fa9e4066Sahrens lr = (lr_create_t *)&itx->itx_lr; 419fa9e4066Sahrens lr->lr_doid = dzp->z_id; 420fa9e4066Sahrens lr->lr_foid = zp->z_id; 4210a586ceaSMark Shellenbaum lr->lr_uid = zp->z_uid; 4220a586ceaSMark Shellenbaum lr->lr_gid = zp->z_gid; 4230a586ceaSMark Shellenbaum lr->lr_mode = zp->z_mode; 4240a586ceaSMark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zp->z_zfsvfs), &lr->lr_gen, 4250a586ceaSMark Shellenbaum sizeof (uint64_t)); 4260a586ceaSMark Shellenbaum (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs), 4270a586ceaSMark Shellenbaum lr->lr_crtime, sizeof (uint64_t) * 2); 428fa9e4066Sahrens bcopy(name, (char *)(lr + 1), namesize); 429fa9e4066Sahrens bcopy(link, (char *)(lr + 1) + namesize, linksize); 430fa9e4066Sahrens 4315002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 432d78b796cSAndreas Jaekel 433d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 434d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_symlink) 435e206ace3SAndreas Jaekel rz_zev_callbacks->rz_zev_znode_symlink(dzp, zp, tx, name, link); 436d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 437fa9e4066Sahrens } 438fa9e4066Sahrens 439fa9e4066Sahrens /* 440f7170741SWill Andrews * Handles TX_RENAME transactions. 441fa9e4066Sahrens */ 442b19a79ecSperrin void 443da6c28aaSamw zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 444*f8e3fee2SAndreas Jaekel znode_t *sdzp, char *sname, znode_t *tdzp, char *dname, znode_t *szp, 445*f8e3fee2SAndreas Jaekel znode_t *tzp) 446fa9e4066Sahrens { 447fa9e4066Sahrens itx_t *itx; 448fa9e4066Sahrens lr_rename_t *lr; 449fa9e4066Sahrens size_t snamesize = strlen(sname) + 1; 450fa9e4066Sahrens size_t dnamesize = strlen(dname) + 1; 451fa9e4066Sahrens 452b24ab676SJeff Bonwick if (zil_replaying(zilog, tx)) 453b19a79ecSperrin return; 454fa9e4066Sahrens 455fa9e4066Sahrens itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize); 456fa9e4066Sahrens lr = (lr_rename_t *)&itx->itx_lr; 457fa9e4066Sahrens lr->lr_sdoid = sdzp->z_id; 458fa9e4066Sahrens lr->lr_tdoid = tdzp->z_id; 459fa9e4066Sahrens bcopy(sname, (char *)(lr + 1), snamesize); 460fa9e4066Sahrens bcopy(dname, (char *)(lr + 1) + snamesize, dnamesize); 46191de656bSNeil Perrin itx->itx_oid = szp->z_id; 462fa9e4066Sahrens 4635002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 464d78b796cSAndreas Jaekel 465d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 466d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_rename) 467d78b796cSAndreas Jaekel rz_zev_callbacks->rz_zev_znode_rename(sdzp, 468*f8e3fee2SAndreas Jaekel sname, tdzp, dname, szp, tzp, tx); 469d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 470fa9e4066Sahrens } 471fa9e4066Sahrens 472fa9e4066Sahrens /* 473f7170741SWill Andrews * Handles TX_WRITE transactions. 474fa9e4066Sahrens */ 475c5c6ffa0Smaybee ssize_t zfs_immediate_write_sz = 32768; 476fa9e4066Sahrens 477b19a79ecSperrin void 478fa9e4066Sahrens zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, 4796ce0521aSperrin znode_t *zp, offset_t off, ssize_t resid, int ioflag) 480fa9e4066Sahrens { 481104e2ed7Sperrin itx_wr_state_t write_state; 4826ce0521aSperrin boolean_t slogging; 483ec533521Sfr157268 uintptr_t fsync_cnt; 484e09fa4daSNeil Perrin ssize_t immediate_write_sz; 485fa9e4066Sahrens 486b24ab676SJeff Bonwick if (zil_replaying(zilog, tx) || zp->z_unlinked) 487b19a79ecSperrin return; 488fa9e4066Sahrens 489e09fa4daSNeil Perrin immediate_write_sz = (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) 490e09fa4daSNeil Perrin ? 0 : zfs_immediate_write_sz; 491e09fa4daSNeil Perrin 492e09fa4daSNeil Perrin slogging = spa_has_slogs(zilog->zl_spa) && 493e09fa4daSNeil Perrin (zilog->zl_logbias == ZFS_LOGBIAS_LATENCY); 494e09fa4daSNeil Perrin if (resid > immediate_write_sz && !slogging && resid <= zp->z_blksz) 495104e2ed7Sperrin write_state = WR_INDIRECT; 496f70bbccaSperrin else if (ioflag & (FSYNC | FDSYNC)) 497104e2ed7Sperrin write_state = WR_COPIED; 498feb08c6bSbillm else 499104e2ed7Sperrin write_state = WR_NEED_COPY; 500feb08c6bSbillm 501ec533521Sfr157268 if ((fsync_cnt = (uintptr_t)tsd_get(zfs_fsyncer_key)) != 0) { 502ec533521Sfr157268 (void) tsd_set(zfs_fsyncer_key, (void *)(fsync_cnt - 1)); 503ec533521Sfr157268 } 504ec533521Sfr157268 5056ce0521aSperrin while (resid) { 5066ce0521aSperrin itx_t *itx; 5076ce0521aSperrin lr_write_t *lr; 5086ce0521aSperrin ssize_t len; 5096ce0521aSperrin 5106ce0521aSperrin /* 5115f8955b4SNeil Perrin * If the write would overflow the largest block then split it. 5126ce0521aSperrin */ 5135f8955b4SNeil Perrin if (write_state != WR_INDIRECT && resid > ZIL_MAX_LOG_DATA) 514b5152584SMatthew Ahrens len = SPA_OLD_MAXBLOCKSIZE >> 1; 5156ce0521aSperrin else 5166ce0521aSperrin len = resid; 5176ce0521aSperrin 518feb08c6bSbillm itx = zil_itx_create(txtype, sizeof (*lr) + 519feb08c6bSbillm (write_state == WR_COPIED ? len : 0)); 520fa9e4066Sahrens lr = (lr_write_t *)&itx->itx_lr; 5216ce0521aSperrin if (write_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os, 5227bfdf011SNeil Perrin zp->z_id, off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) { 523b24ab676SJeff Bonwick zil_itx_destroy(itx); 524feb08c6bSbillm itx = zil_itx_create(txtype, sizeof (*lr)); 525feb08c6bSbillm lr = (lr_write_t *)&itx->itx_lr; 526feb08c6bSbillm write_state = WR_NEED_COPY; 527feb08c6bSbillm } 528feb08c6bSbillm 529feb08c6bSbillm itx->itx_wr_state = write_state; 530abf76b6eSperrin if (write_state == WR_NEED_COPY) 531abf76b6eSperrin itx->itx_sod += len; 532fa9e4066Sahrens lr->lr_foid = zp->z_id; 533fa9e4066Sahrens lr->lr_offset = off; 534fa9e4066Sahrens lr->lr_length = len; 535fa9e4066Sahrens lr->lr_blkoff = 0; 536fa9e4066Sahrens BP_ZERO(&lr->lr_blkptr); 537fa9e4066Sahrens 538fa9e4066Sahrens itx->itx_private = zp->z_zfsvfs; 539fa9e4066Sahrens 5405002558fSNeil Perrin if (!(ioflag & (FSYNC | FDSYNC)) && (zp->z_sync_cnt == 0) && 5415002558fSNeil Perrin (fsync_cnt == 0)) 542ec533521Sfr157268 itx->itx_sync = B_FALSE; 543ec533521Sfr157268 5445002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 5456ce0521aSperrin 546d78b796cSAndreas Jaekel if (ZTOV(zp)->v_type == VREG) 547d78b796cSAndreas Jaekel atomic_add_32(&(zp->z_new_content), 1); 548d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 549d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_write) 550e206ace3SAndreas Jaekel rz_zev_callbacks->rz_zev_znode_write(zp, tx, off, len); 551d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 552d78b796cSAndreas Jaekel 5536ce0521aSperrin off += len; 5546ce0521aSperrin resid -= len; 5556ce0521aSperrin } 556fa9e4066Sahrens } 557fa9e4066Sahrens 558fa9e4066Sahrens /* 559f7170741SWill Andrews * Handles TX_TRUNCATE transactions. 560fa9e4066Sahrens */ 561b19a79ecSperrin void 562fa9e4066Sahrens zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype, 563fa9e4066Sahrens znode_t *zp, uint64_t off, uint64_t len) 564fa9e4066Sahrens { 565fa9e4066Sahrens itx_t *itx; 566fa9e4066Sahrens lr_truncate_t *lr; 567fa9e4066Sahrens 568b24ab676SJeff Bonwick if (zil_replaying(zilog, tx) || zp->z_unlinked) 569b19a79ecSperrin return; 570fa9e4066Sahrens 571fa9e4066Sahrens itx = zil_itx_create(txtype, sizeof (*lr)); 572fa9e4066Sahrens lr = (lr_truncate_t *)&itx->itx_lr; 573fa9e4066Sahrens lr->lr_foid = zp->z_id; 574fa9e4066Sahrens lr->lr_offset = off; 575fa9e4066Sahrens lr->lr_length = len; 576fa9e4066Sahrens 57767bd71c6Sperrin itx->itx_sync = (zp->z_sync_cnt != 0); 5785002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 579d78b796cSAndreas Jaekel 580d78b796cSAndreas Jaekel if (ZTOV(zp)->v_type == VREG) 581d78b796cSAndreas Jaekel atomic_add_32(&(zp->z_new_content), 1); 582d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 583d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_truncate) 584e206ace3SAndreas Jaekel rz_zev_callbacks->rz_zev_znode_truncate(zp, tx, off, len); 585d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 586fa9e4066Sahrens } 587fa9e4066Sahrens 588fa9e4066Sahrens /* 589f7170741SWill Andrews * Handles TX_SETATTR transactions. 590fa9e4066Sahrens */ 591b19a79ecSperrin void 592fa9e4066Sahrens zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, 593da6c28aaSamw znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp) 594fa9e4066Sahrens { 595fa9e4066Sahrens itx_t *itx; 596fa9e4066Sahrens lr_setattr_t *lr; 597da6c28aaSamw xvattr_t *xvap = (xvattr_t *)vap; 598da6c28aaSamw size_t recsize = sizeof (lr_setattr_t); 599da6c28aaSamw void *start; 600da6c28aaSamw 601b24ab676SJeff Bonwick if (zil_replaying(zilog, tx) || zp->z_unlinked) 602b19a79ecSperrin return; 603fa9e4066Sahrens 604da6c28aaSamw /* 605da6c28aaSamw * If XVATTR set, then log record size needs to allow 606da6c28aaSamw * for lr_attr_t + xvattr mask, mapsize and create time 607da6c28aaSamw * plus actual attribute values 608da6c28aaSamw */ 609da6c28aaSamw if (vap->va_mask & AT_XVATTR) 610da6c28aaSamw recsize = sizeof (*lr) + ZIL_XVAT_SIZE(xvap->xva_mapsize); 611da6c28aaSamw 612da6c28aaSamw if (fuidp) 613da6c28aaSamw recsize += fuidp->z_domain_str_sz; 614da6c28aaSamw 615da6c28aaSamw itx = zil_itx_create(txtype, recsize); 616fa9e4066Sahrens lr = (lr_setattr_t *)&itx->itx_lr; 617fa9e4066Sahrens lr->lr_foid = zp->z_id; 618fa9e4066Sahrens lr->lr_mask = (uint64_t)mask_applied; 619fa9e4066Sahrens lr->lr_mode = (uint64_t)vap->va_mode; 620da6c28aaSamw if ((mask_applied & AT_UID) && IS_EPHEMERAL(vap->va_uid)) 621da6c28aaSamw lr->lr_uid = fuidp->z_fuid_owner; 622da6c28aaSamw else 623fa9e4066Sahrens lr->lr_uid = (uint64_t)vap->va_uid; 624da6c28aaSamw 625da6c28aaSamw if ((mask_applied & AT_GID) && IS_EPHEMERAL(vap->va_gid)) 626da6c28aaSamw lr->lr_gid = fuidp->z_fuid_group; 627da6c28aaSamw else 628fa9e4066Sahrens lr->lr_gid = (uint64_t)vap->va_gid; 629da6c28aaSamw 630fa9e4066Sahrens lr->lr_size = (uint64_t)vap->va_size; 631fa9e4066Sahrens ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime); 632fa9e4066Sahrens ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime); 633da6c28aaSamw start = (lr_setattr_t *)(lr + 1); 634da6c28aaSamw if (vap->va_mask & AT_XVATTR) { 635da6c28aaSamw zfs_log_xvattr((lr_attr_t *)start, xvap); 636da6c28aaSamw start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize); 637da6c28aaSamw } 638da6c28aaSamw 639da6c28aaSamw /* 640da6c28aaSamw * Now stick on domain information if any on end 641da6c28aaSamw */ 642da6c28aaSamw 643da6c28aaSamw if (fuidp) 644da6c28aaSamw (void) zfs_log_fuid_domains(fuidp, start); 645fa9e4066Sahrens 64667bd71c6Sperrin itx->itx_sync = (zp->z_sync_cnt != 0); 6475002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 648fa9e4066Sahrens } 649fa9e4066Sahrens 650fa9e4066Sahrens /* 651f7170741SWill Andrews * Handles TX_ACL transactions. 652fa9e4066Sahrens */ 653b19a79ecSperrin void 654da6c28aaSamw zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp, 655da6c28aaSamw vsecattr_t *vsecp, zfs_fuid_info_t *fuidp) 656fa9e4066Sahrens { 657fa9e4066Sahrens itx_t *itx; 658da6c28aaSamw lr_acl_v0_t *lrv0; 659fa9e4066Sahrens lr_acl_t *lr; 660da6c28aaSamw int txtype; 661da6c28aaSamw int lrsize; 662da6c28aaSamw size_t txsize; 663da6c28aaSamw size_t aclbytes = vsecp->vsa_aclentsz; 664da6c28aaSamw 665b24ab676SJeff Bonwick if (zil_replaying(zilog, tx) || zp->z_unlinked) 66631e69ea4Smarks return; 66731e69ea4Smarks 66831e69ea4Smarks txtype = (zp->z_zfsvfs->z_version < ZPL_VERSION_FUID) ? 669da6c28aaSamw TX_ACL_V0 : TX_ACL; 670da6c28aaSamw 671da6c28aaSamw if (txtype == TX_ACL) 672da6c28aaSamw lrsize = sizeof (*lr); 673da6c28aaSamw else 674da6c28aaSamw lrsize = sizeof (*lrv0); 675fa9e4066Sahrens 676569e6c63Smarks txsize = lrsize + 677569e6c63Smarks ((txtype == TX_ACL) ? ZIL_ACE_LENGTH(aclbytes) : aclbytes) + 678569e6c63Smarks (fuidp ? fuidp->z_domain_str_sz : 0) + 67931e69ea4Smarks sizeof (uint64_t) * (fuidp ? fuidp->z_fuid_cnt : 0); 680da6c28aaSamw 681da6c28aaSamw itx = zil_itx_create(txtype, txsize); 682da6c28aaSamw 683fa9e4066Sahrens lr = (lr_acl_t *)&itx->itx_lr; 684fa9e4066Sahrens lr->lr_foid = zp->z_id; 685da6c28aaSamw if (txtype == TX_ACL) { 686da6c28aaSamw lr->lr_acl_bytes = aclbytes; 687da6c28aaSamw lr->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0; 688da6c28aaSamw lr->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0; 689da6c28aaSamw if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) 690da6c28aaSamw lr->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags; 691da6c28aaSamw else 692da6c28aaSamw lr->lr_acl_flags = 0; 693da6c28aaSamw } 694da6c28aaSamw lr->lr_aclcnt = (uint64_t)vsecp->vsa_aclcnt; 695da6c28aaSamw 696da6c28aaSamw if (txtype == TX_ACL_V0) { 697da6c28aaSamw lrv0 = (lr_acl_v0_t *)lr; 698da6c28aaSamw bcopy(vsecp->vsa_aclentp, (ace_t *)(lrv0 + 1), aclbytes); 699da6c28aaSamw } else { 700da6c28aaSamw void *start = (ace_t *)(lr + 1); 701da6c28aaSamw 702da6c28aaSamw bcopy(vsecp->vsa_aclentp, start, aclbytes); 703da6c28aaSamw 704569e6c63Smarks start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes); 705da6c28aaSamw 706da6c28aaSamw if (fuidp) { 707da6c28aaSamw start = zfs_log_fuid_ids(fuidp, start); 708da6c28aaSamw (void) zfs_log_fuid_domains(fuidp, start); 709da6c28aaSamw } 710da6c28aaSamw } 711fa9e4066Sahrens 71267bd71c6Sperrin itx->itx_sync = (zp->z_sync_cnt != 0); 7135002558fSNeil Perrin zil_itx_assign(zilog, itx, tx); 714d78b796cSAndreas Jaekel 715d78b796cSAndreas Jaekel rw_enter(&rz_zev_rwlock, RW_READER); 716d78b796cSAndreas Jaekel if (rz_zev_callbacks && rz_zev_callbacks->rz_zev_znode_acl) 717e206ace3SAndreas Jaekel rz_zev_callbacks->rz_zev_znode_acl(zp, tx); 718d78b796cSAndreas Jaekel rw_exit(&rz_zev_rwlock); 719fa9e4066Sahrens } 720