1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23eda14cbcSMatt Macy * Copyright (c) 2015, 2018 by Delphix. All rights reserved. 242a58b312SMartin Matuska * Copyright (c) 2022 by Pawel Jakub Dawidek 25eda14cbcSMatt Macy */ 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy 28eda14cbcSMatt Macy #include <sys/types.h> 29eda14cbcSMatt Macy #include <sys/param.h> 30eda14cbcSMatt Macy #include <sys/sysmacros.h> 31eda14cbcSMatt Macy #include <sys/cmn_err.h> 32eda14cbcSMatt Macy #include <sys/kmem.h> 33eda14cbcSMatt Macy #include <sys/thread.h> 34eda14cbcSMatt Macy #include <sys/file.h> 35eda14cbcSMatt Macy #include <sys/vfs.h> 36eda14cbcSMatt Macy #include <sys/zfs_znode.h> 37eda14cbcSMatt Macy #include <sys/zfs_dir.h> 38eda14cbcSMatt Macy #include <sys/zil.h> 39eda14cbcSMatt Macy #include <sys/zil_impl.h> 40eda14cbcSMatt Macy #include <sys/byteorder.h> 41eda14cbcSMatt Macy #include <sys/policy.h> 42eda14cbcSMatt Macy #include <sys/stat.h> 43eda14cbcSMatt Macy #include <sys/acl.h> 44eda14cbcSMatt Macy #include <sys/dmu.h> 45eda14cbcSMatt Macy #include <sys/dbuf.h> 46eda14cbcSMatt Macy #include <sys/spa.h> 47eda14cbcSMatt Macy #include <sys/zfs_fuid.h> 48eda14cbcSMatt Macy #include <sys/dsl_dataset.h> 49eda14cbcSMatt Macy 50eda14cbcSMatt Macy /* 51eda14cbcSMatt Macy * These zfs_log_* functions must be called within a dmu tx, in one 52eda14cbcSMatt Macy * of 2 contexts depending on zilog->z_replay: 53eda14cbcSMatt Macy * 54eda14cbcSMatt Macy * Non replay mode 55eda14cbcSMatt Macy * --------------- 56eda14cbcSMatt Macy * We need to record the transaction so that if it is committed to 57eda14cbcSMatt Macy * the Intent Log then it can be replayed. An intent log transaction 58eda14cbcSMatt Macy * structure (itx_t) is allocated and all the information necessary to 59eda14cbcSMatt Macy * possibly replay the transaction is saved in it. The itx is then assigned 60eda14cbcSMatt Macy * a sequence number and inserted in the in-memory list anchored in the zilog. 61eda14cbcSMatt Macy * 62eda14cbcSMatt Macy * Replay mode 63eda14cbcSMatt Macy * ----------- 64eda14cbcSMatt Macy * We need to mark the intent log record as replayed in the log header. 65eda14cbcSMatt Macy * This is done in the same transaction as the replay so that they 66eda14cbcSMatt Macy * commit atomically. 67eda14cbcSMatt Macy */ 68eda14cbcSMatt Macy 69eda14cbcSMatt Macy int 70eda14cbcSMatt Macy zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap) 71eda14cbcSMatt Macy { 72eda14cbcSMatt Macy int isxvattr = (vap->va_mask & ATTR_XVATTR); 73eda14cbcSMatt Macy switch (type) { 74eda14cbcSMatt Macy case Z_FILE: 75eda14cbcSMatt Macy if (vsecp == NULL && !isxvattr) 76eda14cbcSMatt Macy return (TX_CREATE); 77eda14cbcSMatt Macy if (vsecp && isxvattr) 78eda14cbcSMatt Macy return (TX_CREATE_ACL_ATTR); 79eda14cbcSMatt Macy if (vsecp) 80eda14cbcSMatt Macy return (TX_CREATE_ACL); 81eda14cbcSMatt Macy else 82eda14cbcSMatt Macy return (TX_CREATE_ATTR); 83eda14cbcSMatt Macy case Z_DIR: 84eda14cbcSMatt Macy if (vsecp == NULL && !isxvattr) 85eda14cbcSMatt Macy return (TX_MKDIR); 86eda14cbcSMatt Macy if (vsecp && isxvattr) 87eda14cbcSMatt Macy return (TX_MKDIR_ACL_ATTR); 88eda14cbcSMatt Macy if (vsecp) 89eda14cbcSMatt Macy return (TX_MKDIR_ACL); 90eda14cbcSMatt Macy else 91eda14cbcSMatt Macy return (TX_MKDIR_ATTR); 92eda14cbcSMatt Macy case Z_XATTRDIR: 93eda14cbcSMatt Macy return (TX_MKXATTR); 94eda14cbcSMatt Macy } 95eda14cbcSMatt Macy ASSERT(0); 96eda14cbcSMatt Macy return (TX_MAX_TYPE); 97eda14cbcSMatt Macy } 98eda14cbcSMatt Macy 99eda14cbcSMatt Macy /* 100eda14cbcSMatt Macy * build up the log data necessary for logging xvattr_t 101eda14cbcSMatt Macy * First lr_attr_t is initialized. following the lr_attr_t 102eda14cbcSMatt Macy * is the mapsize and attribute bitmap copied from the xvattr_t. 103eda14cbcSMatt Macy * Following the bitmap and bitmapsize two 64 bit words are reserved 104eda14cbcSMatt Macy * for the create time which may be set. Following the create time 105eda14cbcSMatt Macy * records a single 64 bit integer which has the bits to set on 106eda14cbcSMatt Macy * replay for the xvattr. 107eda14cbcSMatt Macy */ 108eda14cbcSMatt Macy static void 109eda14cbcSMatt Macy zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 110eda14cbcSMatt Macy { 111eda14cbcSMatt Macy xoptattr_t *xoap; 112eda14cbcSMatt Macy 113eda14cbcSMatt Macy xoap = xva_getxoptattr(xvap); 114eda14cbcSMatt Macy ASSERT(xoap); 115eda14cbcSMatt Macy 116eda14cbcSMatt Macy lrattr->lr_attr_masksize = xvap->xva_mapsize; 117a0b956f5SMartin Matuska uint32_t *bitmap = &lrattr->lr_attr_bitmap; 118a0b956f5SMartin Matuska for (int i = 0; i != xvap->xva_mapsize; i++, bitmap++) 119eda14cbcSMatt Macy *bitmap = xvap->xva_reqattrmap[i]; 120eda14cbcSMatt Macy 121a0b956f5SMartin Matuska lr_attr_end_t *end = (lr_attr_end_t *)bitmap; 122a0b956f5SMartin Matuska end->lr_attr_attrs = 0; 123a0b956f5SMartin Matuska end->lr_attr_crtime[0] = 0; 124a0b956f5SMartin Matuska end->lr_attr_crtime[1] = 0; 125a0b956f5SMartin Matuska memset(end->lr_attr_scanstamp, 0, AV_SCANSTAMP_SZ); 126a0b956f5SMartin Matuska 127eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_READONLY)) 128a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_readonly == 0) ? 0 : 129eda14cbcSMatt Macy XAT0_READONLY; 130eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) 131a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_hidden == 0) ? 0 : 132eda14cbcSMatt Macy XAT0_HIDDEN; 133eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) 134a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_system == 0) ? 0 : 135eda14cbcSMatt Macy XAT0_SYSTEM; 136eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) 137a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_archive == 0) ? 0 : 138eda14cbcSMatt Macy XAT0_ARCHIVE; 139eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) 140a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_immutable == 0) ? 0 : 141eda14cbcSMatt Macy XAT0_IMMUTABLE; 142eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) 143a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_nounlink == 0) ? 0 : 144eda14cbcSMatt Macy XAT0_NOUNLINK; 145eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) 146a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_appendonly == 0) ? 0 : 147eda14cbcSMatt Macy XAT0_APPENDONLY; 148eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) 149a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_opaque == 0) ? 0 : 150eda14cbcSMatt Macy XAT0_APPENDONLY; 151eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) 152a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_nodump == 0) ? 0 : 153eda14cbcSMatt Macy XAT0_NODUMP; 154eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) 155a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_av_quarantined == 0) ? 0 : 156eda14cbcSMatt Macy XAT0_AV_QUARANTINED; 157eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) 158a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_av_modified == 0) ? 0 : 159eda14cbcSMatt Macy XAT0_AV_MODIFIED; 160eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) 161a0b956f5SMartin Matuska ZFS_TIME_ENCODE(&xoap->xoa_createtime, end->lr_attr_crtime); 162eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) { 163eda14cbcSMatt Macy ASSERT(!XVA_ISSET_REQ(xvap, XAT_PROJID)); 164eda14cbcSMatt Macy 165a0b956f5SMartin Matuska memcpy(end->lr_attr_scanstamp, xoap->xoa_av_scanstamp, 166a0b956f5SMartin Matuska AV_SCANSTAMP_SZ); 167eda14cbcSMatt Macy } else if (XVA_ISSET_REQ(xvap, XAT_PROJID)) { 168eda14cbcSMatt Macy /* 169eda14cbcSMatt Macy * XAT_PROJID and XAT_AV_SCANSTAMP will never be valid 170eda14cbcSMatt Macy * at the same time, so we can share the same space. 171eda14cbcSMatt Macy */ 172a0b956f5SMartin Matuska memcpy(end->lr_attr_scanstamp, &xoap->xoa_projid, 173a0b956f5SMartin Matuska sizeof (uint64_t)); 174eda14cbcSMatt Macy } 175eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) 176a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_reparse == 0) ? 0 : 177eda14cbcSMatt Macy XAT0_REPARSE; 178eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) 179a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_offline == 0) ? 0 : 180eda14cbcSMatt Macy XAT0_OFFLINE; 181eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) 182a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_sparse == 0) ? 0 : 183eda14cbcSMatt Macy XAT0_SPARSE; 184eda14cbcSMatt Macy if (XVA_ISSET_REQ(xvap, XAT_PROJINHERIT)) 185a0b956f5SMartin Matuska end->lr_attr_attrs |= (xoap->xoa_projinherit == 0) ? 0 : 186eda14cbcSMatt Macy XAT0_PROJINHERIT; 187eda14cbcSMatt Macy } 188eda14cbcSMatt Macy 189eda14cbcSMatt Macy static void * 190eda14cbcSMatt Macy zfs_log_fuid_ids(zfs_fuid_info_t *fuidp, void *start) 191eda14cbcSMatt Macy { 192eda14cbcSMatt Macy zfs_fuid_t *zfuid; 193eda14cbcSMatt Macy uint64_t *fuidloc = start; 194eda14cbcSMatt Macy 195eda14cbcSMatt Macy /* First copy in the ACE FUIDs */ 196eda14cbcSMatt Macy for (zfuid = list_head(&fuidp->z_fuids); zfuid; 197eda14cbcSMatt Macy zfuid = list_next(&fuidp->z_fuids, zfuid)) { 198eda14cbcSMatt Macy *fuidloc++ = zfuid->z_logfuid; 199eda14cbcSMatt Macy } 200eda14cbcSMatt Macy return (fuidloc); 201eda14cbcSMatt Macy } 202eda14cbcSMatt Macy 203eda14cbcSMatt Macy 204eda14cbcSMatt Macy static void * 205eda14cbcSMatt Macy zfs_log_fuid_domains(zfs_fuid_info_t *fuidp, void *start) 206eda14cbcSMatt Macy { 207eda14cbcSMatt Macy zfs_fuid_domain_t *zdomain; 208eda14cbcSMatt Macy 209eda14cbcSMatt Macy /* now copy in the domain info, if any */ 210eda14cbcSMatt Macy if (fuidp->z_domain_str_sz != 0) { 211eda14cbcSMatt Macy for (zdomain = list_head(&fuidp->z_domains); zdomain; 212eda14cbcSMatt Macy zdomain = list_next(&fuidp->z_domains, zdomain)) { 213da5137abSMartin Matuska memcpy(start, zdomain->z_domain, 214eda14cbcSMatt Macy strlen(zdomain->z_domain) + 1); 215eda14cbcSMatt Macy start = (caddr_t)start + 216eda14cbcSMatt Macy strlen(zdomain->z_domain) + 1; 217eda14cbcSMatt Macy } 218eda14cbcSMatt Macy } 219eda14cbcSMatt Macy return (start); 220eda14cbcSMatt Macy } 221eda14cbcSMatt Macy 222eda14cbcSMatt Macy /* 223eda14cbcSMatt Macy * If zp is an xattr node, check whether the xattr owner is unlinked. 224eda14cbcSMatt Macy * We don't want to log anything if the owner is unlinked. 225eda14cbcSMatt Macy */ 226eda14cbcSMatt Macy static int 227eda14cbcSMatt Macy zfs_xattr_owner_unlinked(znode_t *zp) 228eda14cbcSMatt Macy { 229eda14cbcSMatt Macy int unlinked = 0; 230eda14cbcSMatt Macy znode_t *dzp; 231eda14cbcSMatt Macy #ifdef __FreeBSD__ 232eda14cbcSMatt Macy znode_t *tzp = zp; 233eda14cbcSMatt Macy 234eda14cbcSMatt Macy /* 235eda14cbcSMatt Macy * zrele drops the vnode lock which violates the VOP locking contract 236eda14cbcSMatt Macy * on FreeBSD. See comment at the top of zfs_replay.c for more detail. 237eda14cbcSMatt Macy */ 238eda14cbcSMatt Macy /* 239eda14cbcSMatt Macy * if zp is XATTR node, keep walking up via z_xattr_parent until we 240eda14cbcSMatt Macy * get the owner 241eda14cbcSMatt Macy */ 242eda14cbcSMatt Macy while (tzp->z_pflags & ZFS_XATTR) { 243eda14cbcSMatt Macy ASSERT3U(zp->z_xattr_parent, !=, 0); 244eda14cbcSMatt Macy if (zfs_zget(ZTOZSB(tzp), tzp->z_xattr_parent, &dzp) != 0) { 245eda14cbcSMatt Macy unlinked = 1; 246eda14cbcSMatt Macy break; 247eda14cbcSMatt Macy } 248eda14cbcSMatt Macy 249eda14cbcSMatt Macy if (tzp != zp) 250eda14cbcSMatt Macy zrele(tzp); 251eda14cbcSMatt Macy tzp = dzp; 252eda14cbcSMatt Macy unlinked = tzp->z_unlinked; 253eda14cbcSMatt Macy } 254eda14cbcSMatt Macy if (tzp != zp) 255eda14cbcSMatt Macy zrele(tzp); 256eda14cbcSMatt Macy #else 257eda14cbcSMatt Macy zhold(zp); 258eda14cbcSMatt Macy /* 259eda14cbcSMatt Macy * if zp is XATTR node, keep walking up via z_xattr_parent until we 260eda14cbcSMatt Macy * get the owner 261eda14cbcSMatt Macy */ 262eda14cbcSMatt Macy while (zp->z_pflags & ZFS_XATTR) { 263eda14cbcSMatt Macy ASSERT3U(zp->z_xattr_parent, !=, 0); 264eda14cbcSMatt Macy if (zfs_zget(ZTOZSB(zp), zp->z_xattr_parent, &dzp) != 0) { 265eda14cbcSMatt Macy unlinked = 1; 266eda14cbcSMatt Macy break; 267eda14cbcSMatt Macy } 268eda14cbcSMatt Macy 269eda14cbcSMatt Macy zrele(zp); 270eda14cbcSMatt Macy zp = dzp; 271eda14cbcSMatt Macy unlinked = zp->z_unlinked; 272eda14cbcSMatt Macy } 273eda14cbcSMatt Macy zrele(zp); 274eda14cbcSMatt Macy #endif 275eda14cbcSMatt Macy return (unlinked); 276eda14cbcSMatt Macy } 277eda14cbcSMatt Macy 278eda14cbcSMatt Macy /* 279eda14cbcSMatt Macy * Handles TX_CREATE, TX_CREATE_ATTR, TX_MKDIR, TX_MKDIR_ATTR and 280eda14cbcSMatt Macy * TK_MKXATTR transactions. 281eda14cbcSMatt Macy * 282eda14cbcSMatt Macy * TX_CREATE and TX_MKDIR are standard creates, but they may have FUID 283eda14cbcSMatt Macy * domain information appended prior to the name. In this case the 284eda14cbcSMatt Macy * uid/gid in the log record will be a log centric FUID. 285eda14cbcSMatt Macy * 286eda14cbcSMatt Macy * TX_CREATE_ACL_ATTR and TX_MKDIR_ACL_ATTR handle special creates that 287eda14cbcSMatt Macy * may contain attributes, ACL and optional fuid information. 288eda14cbcSMatt Macy * 289eda14cbcSMatt Macy * TX_CREATE_ACL and TX_MKDIR_ACL handle special creates that specify 290eda14cbcSMatt Macy * and ACL and normal users/groups in the ACEs. 291eda14cbcSMatt Macy * 292eda14cbcSMatt Macy * There may be an optional xvattr attribute information similar 293eda14cbcSMatt Macy * to zfs_log_setattr. 294eda14cbcSMatt Macy * 295eda14cbcSMatt Macy * Also, after the file name "domain" strings may be appended. 296eda14cbcSMatt Macy */ 297eda14cbcSMatt Macy void 298eda14cbcSMatt Macy zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 299180f8225SMatt Macy znode_t *dzp, znode_t *zp, const char *name, vsecattr_t *vsecp, 300eda14cbcSMatt Macy zfs_fuid_info_t *fuidp, vattr_t *vap) 301eda14cbcSMatt Macy { 302eda14cbcSMatt Macy itx_t *itx; 303eda14cbcSMatt Macy lr_create_t *lr; 304eda14cbcSMatt Macy lr_acl_create_t *lracl; 305eda14cbcSMatt Macy size_t aclsize = 0; 306eda14cbcSMatt Macy size_t xvatsize = 0; 307eda14cbcSMatt Macy size_t txsize; 308eda14cbcSMatt Macy xvattr_t *xvap = (xvattr_t *)vap; 309eda14cbcSMatt Macy void *end; 310eda14cbcSMatt Macy size_t lrsize; 311eda14cbcSMatt Macy size_t namesize = strlen(name) + 1; 312eda14cbcSMatt Macy size_t fuidsz = 0; 313eda14cbcSMatt Macy 314eda14cbcSMatt Macy if (zil_replaying(zilog, tx) || zfs_xattr_owner_unlinked(dzp)) 315eda14cbcSMatt Macy return; 316eda14cbcSMatt Macy 317eda14cbcSMatt Macy /* 318eda14cbcSMatt Macy * If we have FUIDs present then add in space for 319eda14cbcSMatt Macy * domains and ACE fuid's if any. 320eda14cbcSMatt Macy */ 321eda14cbcSMatt Macy if (fuidp) { 322eda14cbcSMatt Macy fuidsz += fuidp->z_domain_str_sz; 323eda14cbcSMatt Macy fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t); 324eda14cbcSMatt Macy } 325eda14cbcSMatt Macy 326eda14cbcSMatt Macy if (vap->va_mask & ATTR_XVATTR) 327eda14cbcSMatt Macy xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize); 328eda14cbcSMatt Macy 329eda14cbcSMatt Macy if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR || 330eda14cbcSMatt Macy (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR || 331eda14cbcSMatt Macy (int)txtype == TX_MKXATTR) { 332eda14cbcSMatt Macy txsize = sizeof (*lr) + namesize + fuidsz + xvatsize; 333eda14cbcSMatt Macy lrsize = sizeof (*lr); 334eda14cbcSMatt Macy } else { 335eda14cbcSMatt Macy txsize = 336eda14cbcSMatt Macy sizeof (lr_acl_create_t) + namesize + fuidsz + 337eda14cbcSMatt Macy ZIL_ACE_LENGTH(aclsize) + xvatsize; 338eda14cbcSMatt Macy lrsize = sizeof (lr_acl_create_t); 339eda14cbcSMatt Macy } 340eda14cbcSMatt Macy 341eda14cbcSMatt Macy itx = zil_itx_create(txtype, txsize); 342eda14cbcSMatt Macy 343eda14cbcSMatt Macy lr = (lr_create_t *)&itx->itx_lr; 344eda14cbcSMatt Macy lr->lr_doid = dzp->z_id; 345eda14cbcSMatt Macy lr->lr_foid = zp->z_id; 346eda14cbcSMatt Macy /* Store dnode slot count in 8 bits above object id. */ 347eda14cbcSMatt Macy LR_FOID_SET_SLOTS(lr->lr_foid, zp->z_dnodesize >> DNODE_SHIFT); 348eda14cbcSMatt Macy lr->lr_mode = zp->z_mode; 349eda14cbcSMatt Macy if (!IS_EPHEMERAL(KUID_TO_SUID(ZTOUID(zp)))) { 350eda14cbcSMatt Macy lr->lr_uid = (uint64_t)KUID_TO_SUID(ZTOUID(zp)); 351eda14cbcSMatt Macy } else { 352eda14cbcSMatt Macy lr->lr_uid = fuidp->z_fuid_owner; 353eda14cbcSMatt Macy } 354eda14cbcSMatt Macy if (!IS_EPHEMERAL(KGID_TO_SGID(ZTOGID(zp)))) { 355eda14cbcSMatt Macy lr->lr_gid = (uint64_t)KGID_TO_SGID(ZTOGID(zp)); 356eda14cbcSMatt Macy } else { 357eda14cbcSMatt Macy lr->lr_gid = fuidp->z_fuid_group; 358eda14cbcSMatt Macy } 359eda14cbcSMatt Macy (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen, 360eda14cbcSMatt Macy sizeof (uint64_t)); 361eda14cbcSMatt Macy (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)), 362eda14cbcSMatt Macy lr->lr_crtime, sizeof (uint64_t) * 2); 363eda14cbcSMatt Macy 364eda14cbcSMatt Macy if (sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(zp)), &lr->lr_rdev, 365eda14cbcSMatt Macy sizeof (lr->lr_rdev)) != 0) 366eda14cbcSMatt Macy lr->lr_rdev = 0; 367eda14cbcSMatt Macy 368eda14cbcSMatt Macy /* 369eda14cbcSMatt Macy * Fill in xvattr info if any 370eda14cbcSMatt Macy */ 371eda14cbcSMatt Macy if (vap->va_mask & ATTR_XVATTR) { 372eda14cbcSMatt Macy zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap); 373eda14cbcSMatt Macy end = (caddr_t)lr + lrsize + xvatsize; 374eda14cbcSMatt Macy } else { 375eda14cbcSMatt Macy end = (caddr_t)lr + lrsize; 376eda14cbcSMatt Macy } 377eda14cbcSMatt Macy 378eda14cbcSMatt Macy /* Now fill in any ACL info */ 379eda14cbcSMatt Macy 380eda14cbcSMatt Macy if (vsecp) { 381eda14cbcSMatt Macy lracl = (lr_acl_create_t *)&itx->itx_lr; 382eda14cbcSMatt Macy lracl->lr_aclcnt = vsecp->vsa_aclcnt; 383eda14cbcSMatt Macy lracl->lr_acl_bytes = aclsize; 384eda14cbcSMatt Macy lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0; 385eda14cbcSMatt Macy lracl->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0; 386eda14cbcSMatt Macy if (vsecp->vsa_aclflags & VSA_ACE_ACLFLAGS) 387eda14cbcSMatt Macy lracl->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags; 388eda14cbcSMatt Macy else 389eda14cbcSMatt Macy lracl->lr_acl_flags = 0; 390eda14cbcSMatt Macy 391da5137abSMartin Matuska memcpy(end, vsecp->vsa_aclentp, aclsize); 392eda14cbcSMatt Macy end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize); 393eda14cbcSMatt Macy } 394eda14cbcSMatt Macy 395eda14cbcSMatt Macy /* drop in FUID info */ 396eda14cbcSMatt Macy if (fuidp) { 397eda14cbcSMatt Macy end = zfs_log_fuid_ids(fuidp, end); 398eda14cbcSMatt Macy end = zfs_log_fuid_domains(fuidp, end); 399eda14cbcSMatt Macy } 400eda14cbcSMatt Macy /* 401eda14cbcSMatt Macy * Now place file name in log record 402eda14cbcSMatt Macy */ 403da5137abSMartin Matuska memcpy(end, name, namesize); 404eda14cbcSMatt Macy 405eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 406eda14cbcSMatt Macy } 407eda14cbcSMatt Macy 408eda14cbcSMatt Macy /* 409eda14cbcSMatt Macy * Handles both TX_REMOVE and TX_RMDIR transactions. 410eda14cbcSMatt Macy */ 411eda14cbcSMatt Macy void 412eda14cbcSMatt Macy zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 413180f8225SMatt Macy znode_t *dzp, const char *name, uint64_t foid, boolean_t unlinked) 414eda14cbcSMatt Macy { 415eda14cbcSMatt Macy itx_t *itx; 416eda14cbcSMatt Macy lr_remove_t *lr; 417eda14cbcSMatt Macy size_t namesize = strlen(name) + 1; 418eda14cbcSMatt Macy 419eda14cbcSMatt Macy if (zil_replaying(zilog, tx) || zfs_xattr_owner_unlinked(dzp)) 420eda14cbcSMatt Macy return; 421eda14cbcSMatt Macy 422eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr) + namesize); 423eda14cbcSMatt Macy lr = (lr_remove_t *)&itx->itx_lr; 424eda14cbcSMatt Macy lr->lr_doid = dzp->z_id; 425da5137abSMartin Matuska memcpy(lr + 1, name, namesize); 426eda14cbcSMatt Macy 427eda14cbcSMatt Macy itx->itx_oid = foid; 428eda14cbcSMatt Macy 429eda14cbcSMatt Macy /* 430eda14cbcSMatt Macy * Object ids can be re-instantiated in the next txg so 431eda14cbcSMatt Macy * remove any async transactions to avoid future leaks. 432eda14cbcSMatt Macy * This can happen if a fsync occurs on the re-instantiated 433eda14cbcSMatt Macy * object for a WR_INDIRECT or WR_NEED_COPY write, which gets 434eda14cbcSMatt Macy * the new file data and flushes a write record for the old object. 435eda14cbcSMatt Macy */ 436eda14cbcSMatt Macy if (unlinked) { 437eda14cbcSMatt Macy ASSERT((txtype & ~TX_CI) == TX_REMOVE); 438eda14cbcSMatt Macy zil_remove_async(zilog, foid); 439eda14cbcSMatt Macy } 440eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 441eda14cbcSMatt Macy } 442eda14cbcSMatt Macy 443eda14cbcSMatt Macy /* 444eda14cbcSMatt Macy * Handles TX_LINK transactions. 445eda14cbcSMatt Macy */ 446eda14cbcSMatt Macy void 447eda14cbcSMatt Macy zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 448180f8225SMatt Macy znode_t *dzp, znode_t *zp, const char *name) 449eda14cbcSMatt Macy { 450eda14cbcSMatt Macy itx_t *itx; 451eda14cbcSMatt Macy lr_link_t *lr; 452eda14cbcSMatt Macy size_t namesize = strlen(name) + 1; 453eda14cbcSMatt Macy 454eda14cbcSMatt Macy if (zil_replaying(zilog, tx)) 455eda14cbcSMatt Macy return; 456eda14cbcSMatt Macy 457eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr) + namesize); 458eda14cbcSMatt Macy lr = (lr_link_t *)&itx->itx_lr; 459eda14cbcSMatt Macy lr->lr_doid = dzp->z_id; 460eda14cbcSMatt Macy lr->lr_link_obj = zp->z_id; 461da5137abSMartin Matuska memcpy(lr + 1, name, namesize); 462eda14cbcSMatt Macy 463eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 464eda14cbcSMatt Macy } 465eda14cbcSMatt Macy 466eda14cbcSMatt Macy /* 467eda14cbcSMatt Macy * Handles TX_SYMLINK transactions. 468eda14cbcSMatt Macy */ 469eda14cbcSMatt Macy void 470eda14cbcSMatt Macy zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 471180f8225SMatt Macy znode_t *dzp, znode_t *zp, const char *name, const char *link) 472eda14cbcSMatt Macy { 473eda14cbcSMatt Macy itx_t *itx; 474eda14cbcSMatt Macy lr_create_t *lr; 475eda14cbcSMatt Macy size_t namesize = strlen(name) + 1; 476eda14cbcSMatt Macy size_t linksize = strlen(link) + 1; 477eda14cbcSMatt Macy 478eda14cbcSMatt Macy if (zil_replaying(zilog, tx)) 479eda14cbcSMatt Macy return; 480eda14cbcSMatt Macy 481eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize); 482eda14cbcSMatt Macy lr = (lr_create_t *)&itx->itx_lr; 483eda14cbcSMatt Macy lr->lr_doid = dzp->z_id; 484eda14cbcSMatt Macy lr->lr_foid = zp->z_id; 485eda14cbcSMatt Macy lr->lr_uid = KUID_TO_SUID(ZTOUID(zp)); 486eda14cbcSMatt Macy lr->lr_gid = KGID_TO_SGID(ZTOGID(zp)); 487eda14cbcSMatt Macy lr->lr_mode = zp->z_mode; 488eda14cbcSMatt Macy (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen, 489eda14cbcSMatt Macy sizeof (uint64_t)); 490eda14cbcSMatt Macy (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)), 491eda14cbcSMatt Macy lr->lr_crtime, sizeof (uint64_t) * 2); 492da5137abSMartin Matuska memcpy((char *)(lr + 1), name, namesize); 493da5137abSMartin Matuska memcpy((char *)(lr + 1) + namesize, link, linksize); 494eda14cbcSMatt Macy 495eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 496eda14cbcSMatt Macy } 497eda14cbcSMatt Macy 498dbd5678dSMartin Matuska static void 499dbd5678dSMartin Matuska do_zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp, 500180f8225SMatt Macy const char *sname, znode_t *tdzp, const char *dname, znode_t *szp) 501eda14cbcSMatt Macy { 502eda14cbcSMatt Macy itx_t *itx; 503eda14cbcSMatt Macy lr_rename_t *lr; 504eda14cbcSMatt Macy size_t snamesize = strlen(sname) + 1; 505eda14cbcSMatt Macy size_t dnamesize = strlen(dname) + 1; 506eda14cbcSMatt Macy 507eda14cbcSMatt Macy if (zil_replaying(zilog, tx)) 508eda14cbcSMatt Macy return; 509eda14cbcSMatt Macy 510eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize); 511eda14cbcSMatt Macy lr = (lr_rename_t *)&itx->itx_lr; 512eda14cbcSMatt Macy lr->lr_sdoid = sdzp->z_id; 513eda14cbcSMatt Macy lr->lr_tdoid = tdzp->z_id; 514da5137abSMartin Matuska memcpy((char *)(lr + 1), sname, snamesize); 515da5137abSMartin Matuska memcpy((char *)(lr + 1) + snamesize, dname, dnamesize); 516eda14cbcSMatt Macy itx->itx_oid = szp->z_id; 517eda14cbcSMatt Macy 518eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 519eda14cbcSMatt Macy } 520eda14cbcSMatt Macy 521eda14cbcSMatt Macy /* 522dbd5678dSMartin Matuska * Handles TX_RENAME transactions. 523dbd5678dSMartin Matuska */ 524dbd5678dSMartin Matuska void 525dbd5678dSMartin Matuska zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp, 526dbd5678dSMartin Matuska const char *sname, znode_t *tdzp, const char *dname, znode_t *szp) 527dbd5678dSMartin Matuska { 528dbd5678dSMartin Matuska txtype |= TX_RENAME; 529dbd5678dSMartin Matuska do_zfs_log_rename(zilog, tx, txtype, sdzp, sname, tdzp, dname, szp); 530dbd5678dSMartin Matuska } 531dbd5678dSMartin Matuska 532dbd5678dSMartin Matuska /* 533dbd5678dSMartin Matuska * Handles TX_RENAME_EXCHANGE transactions. 534dbd5678dSMartin Matuska */ 535dbd5678dSMartin Matuska void 536dbd5678dSMartin Matuska zfs_log_rename_exchange(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 537dbd5678dSMartin Matuska znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname, 538dbd5678dSMartin Matuska znode_t *szp) 539dbd5678dSMartin Matuska { 540dbd5678dSMartin Matuska txtype |= TX_RENAME_EXCHANGE; 541dbd5678dSMartin Matuska do_zfs_log_rename(zilog, tx, txtype, sdzp, sname, tdzp, dname, szp); 542dbd5678dSMartin Matuska } 543dbd5678dSMartin Matuska 544dbd5678dSMartin Matuska /* 545dbd5678dSMartin Matuska * Handles TX_RENAME_WHITEOUT transactions. 546dbd5678dSMartin Matuska * 547dbd5678dSMartin Matuska * Unfortunately we cannot reuse do_zfs_log_rename because we we need to call 548dbd5678dSMartin Matuska * zfs_mknode() on replay which requires stashing bits as with TX_CREATE. 549dbd5678dSMartin Matuska */ 550dbd5678dSMartin Matuska void 551dbd5678dSMartin Matuska zfs_log_rename_whiteout(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, 552dbd5678dSMartin Matuska znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname, 553dbd5678dSMartin Matuska znode_t *szp, znode_t *wzp) 554dbd5678dSMartin Matuska { 555dbd5678dSMartin Matuska itx_t *itx; 556dbd5678dSMartin Matuska lr_rename_whiteout_t *lr; 557dbd5678dSMartin Matuska size_t snamesize = strlen(sname) + 1; 558dbd5678dSMartin Matuska size_t dnamesize = strlen(dname) + 1; 559dbd5678dSMartin Matuska 560dbd5678dSMartin Matuska if (zil_replaying(zilog, tx)) 561dbd5678dSMartin Matuska return; 562dbd5678dSMartin Matuska 563dbd5678dSMartin Matuska txtype |= TX_RENAME_WHITEOUT; 564dbd5678dSMartin Matuska itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize); 565dbd5678dSMartin Matuska lr = (lr_rename_whiteout_t *)&itx->itx_lr; 566dbd5678dSMartin Matuska lr->lr_rename.lr_sdoid = sdzp->z_id; 567dbd5678dSMartin Matuska lr->lr_rename.lr_tdoid = tdzp->z_id; 568dbd5678dSMartin Matuska 569dbd5678dSMartin Matuska /* 570dbd5678dSMartin Matuska * RENAME_WHITEOUT will create an entry at the source znode, so we need 571dbd5678dSMartin Matuska * to store the same data that the equivalent call to zfs_log_create() 572dbd5678dSMartin Matuska * would. 573dbd5678dSMartin Matuska */ 574dbd5678dSMartin Matuska lr->lr_wfoid = wzp->z_id; 575dbd5678dSMartin Matuska LR_FOID_SET_SLOTS(lr->lr_wfoid, wzp->z_dnodesize >> DNODE_SHIFT); 576dbd5678dSMartin Matuska (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(wzp)), &lr->lr_wgen, 577dbd5678dSMartin Matuska sizeof (uint64_t)); 578dbd5678dSMartin Matuska (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(wzp)), 579dbd5678dSMartin Matuska lr->lr_wcrtime, sizeof (uint64_t) * 2); 580dbd5678dSMartin Matuska lr->lr_wmode = wzp->z_mode; 581dbd5678dSMartin Matuska lr->lr_wuid = (uint64_t)KUID_TO_SUID(ZTOUID(wzp)); 582dbd5678dSMartin Matuska lr->lr_wgid = (uint64_t)KGID_TO_SGID(ZTOGID(wzp)); 583dbd5678dSMartin Matuska 584dbd5678dSMartin Matuska /* 585dbd5678dSMartin Matuska * This rdev will always be makdevice(0, 0) but because the ZIL log and 586dbd5678dSMartin Matuska * replay code needs to be platform independent (and there is no 587dbd5678dSMartin Matuska * platform independent makdev()) we need to copy the one created 588dbd5678dSMartin Matuska * during the rename operation. 589dbd5678dSMartin Matuska */ 590dbd5678dSMartin Matuska (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(wzp)), &lr->lr_wrdev, 591dbd5678dSMartin Matuska sizeof (lr->lr_wrdev)); 592dbd5678dSMartin Matuska 593dbd5678dSMartin Matuska memcpy((char *)(lr + 1), sname, snamesize); 594dbd5678dSMartin Matuska memcpy((char *)(lr + 1) + snamesize, dname, dnamesize); 595dbd5678dSMartin Matuska itx->itx_oid = szp->z_id; 596dbd5678dSMartin Matuska 597dbd5678dSMartin Matuska zil_itx_assign(zilog, itx, tx); 598dbd5678dSMartin Matuska } 599dbd5678dSMartin Matuska 600dbd5678dSMartin Matuska /* 601eda14cbcSMatt Macy * zfs_log_write() handles TX_WRITE transactions. The specified callback is 602eda14cbcSMatt Macy * called as soon as the write is on stable storage (be it via a DMU sync or a 603eda14cbcSMatt Macy * ZIL commit). 604eda14cbcSMatt Macy */ 605dbd5678dSMartin Matuska static int64_t zfs_immediate_write_sz = 32768; 606eda14cbcSMatt Macy 607eda14cbcSMatt Macy void 608eda14cbcSMatt Macy zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, 609*f8b1db88SMartin Matuska znode_t *zp, offset_t off, ssize_t resid, boolean_t commit, 610eda14cbcSMatt Macy zil_callback_t callback, void *callback_data) 611eda14cbcSMatt Macy { 612eda14cbcSMatt Macy dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl); 613eda14cbcSMatt Macy uint32_t blocksize = zp->z_blksz; 614eda14cbcSMatt Macy itx_wr_state_t write_state; 615f9693befSMartin Matuska uint64_t gen = 0; 6163f9d360cSMartin Matuska ssize_t size = resid; 617eda14cbcSMatt Macy 618eda14cbcSMatt Macy if (zil_replaying(zilog, tx) || zp->z_unlinked || 619eda14cbcSMatt Macy zfs_xattr_owner_unlinked(zp)) { 620eda14cbcSMatt Macy if (callback != NULL) 621eda14cbcSMatt Macy callback(callback_data); 622eda14cbcSMatt Macy return; 623eda14cbcSMatt Macy } 624eda14cbcSMatt Macy 625eda14cbcSMatt Macy if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT) 626eda14cbcSMatt Macy write_state = WR_INDIRECT; 627eda14cbcSMatt Macy else if (!spa_has_slogs(zilog->zl_spa) && 628eda14cbcSMatt Macy resid >= zfs_immediate_write_sz) 629eda14cbcSMatt Macy write_state = WR_INDIRECT; 630*f8b1db88SMartin Matuska else if (commit) 631eda14cbcSMatt Macy write_state = WR_COPIED; 632eda14cbcSMatt Macy else 633eda14cbcSMatt Macy write_state = WR_NEED_COPY; 634eda14cbcSMatt Macy 635f9693befSMartin Matuska (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &gen, 636f9693befSMartin Matuska sizeof (gen)); 637f9693befSMartin Matuska 638eda14cbcSMatt Macy while (resid) { 639eda14cbcSMatt Macy itx_t *itx; 640eda14cbcSMatt Macy lr_write_t *lr; 641eda14cbcSMatt Macy itx_wr_state_t wr_state = write_state; 642eda14cbcSMatt Macy ssize_t len = resid; 643eda14cbcSMatt Macy 644eda14cbcSMatt Macy /* 645eda14cbcSMatt Macy * A WR_COPIED record must fit entirely in one log block. 646eda14cbcSMatt Macy * Large writes can use WR_NEED_COPY, which the ZIL will 647eda14cbcSMatt Macy * split into multiple records across several log blocks 648eda14cbcSMatt Macy * if necessary. 649eda14cbcSMatt Macy */ 650eda14cbcSMatt Macy if (wr_state == WR_COPIED && 651eda14cbcSMatt Macy resid > zil_max_copied_data(zilog)) 652eda14cbcSMatt Macy wr_state = WR_NEED_COPY; 653eda14cbcSMatt Macy else if (wr_state == WR_INDIRECT) 654eda14cbcSMatt Macy len = MIN(blocksize - P2PHASE(off, blocksize), resid); 655eda14cbcSMatt Macy 656eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr) + 657eda14cbcSMatt Macy (wr_state == WR_COPIED ? len : 0)); 658eda14cbcSMatt Macy lr = (lr_write_t *)&itx->itx_lr; 659eda14cbcSMatt Macy 660c40487d4SMatt Macy /* 661c40487d4SMatt Macy * For WR_COPIED records, copy the data into the lr_write_t. 662c40487d4SMatt Macy */ 663c40487d4SMatt Macy if (wr_state == WR_COPIED) { 664c40487d4SMatt Macy int err; 665eda14cbcSMatt Macy DB_DNODE_ENTER(db); 666c40487d4SMatt Macy err = dmu_read_by_dnode(DB_DNODE(db), off, len, lr + 1, 667c40487d4SMatt Macy DMU_READ_NO_PREFETCH); 668c40487d4SMatt Macy if (err != 0) { 669eda14cbcSMatt Macy zil_itx_destroy(itx); 670eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr)); 671eda14cbcSMatt Macy lr = (lr_write_t *)&itx->itx_lr; 672eda14cbcSMatt Macy wr_state = WR_NEED_COPY; 673eda14cbcSMatt Macy } 674eda14cbcSMatt Macy DB_DNODE_EXIT(db); 675c40487d4SMatt Macy } 676eda14cbcSMatt Macy 677eda14cbcSMatt Macy itx->itx_wr_state = wr_state; 678eda14cbcSMatt Macy lr->lr_foid = zp->z_id; 679eda14cbcSMatt Macy lr->lr_offset = off; 680eda14cbcSMatt Macy lr->lr_length = len; 681eda14cbcSMatt Macy lr->lr_blkoff = 0; 682eda14cbcSMatt Macy BP_ZERO(&lr->lr_blkptr); 683eda14cbcSMatt Macy 684eda14cbcSMatt Macy itx->itx_private = ZTOZSB(zp); 685*f8b1db88SMartin Matuska itx->itx_sync = (zp->z_sync_cnt != 0); 686f9693befSMartin Matuska itx->itx_gen = gen; 687eda14cbcSMatt Macy 688eda14cbcSMatt Macy itx->itx_callback = callback; 689eda14cbcSMatt Macy itx->itx_callback_data = callback_data; 690eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 691eda14cbcSMatt Macy 692eda14cbcSMatt Macy off += len; 693eda14cbcSMatt Macy resid -= len; 694eda14cbcSMatt Macy } 6953f9d360cSMartin Matuska 6963f9d360cSMartin Matuska if (write_state == WR_COPIED || write_state == WR_NEED_COPY) { 6973f9d360cSMartin Matuska dsl_pool_wrlog_count(zilog->zl_dmu_pool, size, tx->tx_txg); 6983f9d360cSMartin Matuska } 699eda14cbcSMatt Macy } 700eda14cbcSMatt Macy 701eda14cbcSMatt Macy /* 702eda14cbcSMatt Macy * Handles TX_TRUNCATE transactions. 703eda14cbcSMatt Macy */ 704eda14cbcSMatt Macy void 705eda14cbcSMatt Macy zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype, 706eda14cbcSMatt Macy znode_t *zp, uint64_t off, uint64_t len) 707eda14cbcSMatt Macy { 708eda14cbcSMatt Macy itx_t *itx; 709eda14cbcSMatt Macy lr_truncate_t *lr; 710eda14cbcSMatt Macy 711eda14cbcSMatt Macy if (zil_replaying(zilog, tx) || zp->z_unlinked || 712eda14cbcSMatt Macy zfs_xattr_owner_unlinked(zp)) 713eda14cbcSMatt Macy return; 714eda14cbcSMatt Macy 715eda14cbcSMatt Macy itx = zil_itx_create(txtype, sizeof (*lr)); 716eda14cbcSMatt Macy lr = (lr_truncate_t *)&itx->itx_lr; 717eda14cbcSMatt Macy lr->lr_foid = zp->z_id; 718eda14cbcSMatt Macy lr->lr_offset = off; 719eda14cbcSMatt Macy lr->lr_length = len; 720eda14cbcSMatt Macy 721eda14cbcSMatt Macy itx->itx_sync = (zp->z_sync_cnt != 0); 722eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 723eda14cbcSMatt Macy } 724eda14cbcSMatt Macy 725eda14cbcSMatt Macy /* 726eda14cbcSMatt Macy * Handles TX_SETATTR transactions. 727eda14cbcSMatt Macy */ 728eda14cbcSMatt Macy void 729eda14cbcSMatt Macy zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, 730eda14cbcSMatt Macy znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp) 731eda14cbcSMatt Macy { 732eda14cbcSMatt Macy itx_t *itx; 733eda14cbcSMatt Macy lr_setattr_t *lr; 734eda14cbcSMatt Macy xvattr_t *xvap = (xvattr_t *)vap; 735eda14cbcSMatt Macy size_t recsize = sizeof (lr_setattr_t); 736eda14cbcSMatt Macy void *start; 737eda14cbcSMatt Macy 738eda14cbcSMatt Macy if (zil_replaying(zilog, tx) || zp->z_unlinked) 739eda14cbcSMatt Macy return; 740eda14cbcSMatt Macy 741eda14cbcSMatt Macy /* 742eda14cbcSMatt Macy * If XVATTR set, then log record size needs to allow 743eda14cbcSMatt Macy * for lr_attr_t + xvattr mask, mapsize and create time 744eda14cbcSMatt Macy * plus actual attribute values 745eda14cbcSMatt Macy */ 746eda14cbcSMatt Macy if (vap->va_mask & ATTR_XVATTR) 747eda14cbcSMatt Macy recsize = sizeof (*lr) + ZIL_XVAT_SIZE(xvap->xva_mapsize); 748eda14cbcSMatt Macy 749eda14cbcSMatt Macy if (fuidp) 750eda14cbcSMatt Macy recsize += fuidp->z_domain_str_sz; 751eda14cbcSMatt Macy 752eda14cbcSMatt Macy itx = zil_itx_create(txtype, recsize); 753eda14cbcSMatt Macy lr = (lr_setattr_t *)&itx->itx_lr; 754eda14cbcSMatt Macy lr->lr_foid = zp->z_id; 755eda14cbcSMatt Macy lr->lr_mask = (uint64_t)mask_applied; 756eda14cbcSMatt Macy lr->lr_mode = (uint64_t)vap->va_mode; 757eda14cbcSMatt Macy if ((mask_applied & ATTR_UID) && IS_EPHEMERAL(vap->va_uid)) 758eda14cbcSMatt Macy lr->lr_uid = fuidp->z_fuid_owner; 759eda14cbcSMatt Macy else 760eda14cbcSMatt Macy lr->lr_uid = (uint64_t)vap->va_uid; 761eda14cbcSMatt Macy 762eda14cbcSMatt Macy if ((mask_applied & ATTR_GID) && IS_EPHEMERAL(vap->va_gid)) 763eda14cbcSMatt Macy lr->lr_gid = fuidp->z_fuid_group; 764eda14cbcSMatt Macy else 765eda14cbcSMatt Macy lr->lr_gid = (uint64_t)vap->va_gid; 766eda14cbcSMatt Macy 767eda14cbcSMatt Macy lr->lr_size = (uint64_t)vap->va_size; 768eda14cbcSMatt Macy ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime); 769eda14cbcSMatt Macy ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime); 770eda14cbcSMatt Macy start = (lr_setattr_t *)(lr + 1); 771eda14cbcSMatt Macy if (vap->va_mask & ATTR_XVATTR) { 772eda14cbcSMatt Macy zfs_log_xvattr((lr_attr_t *)start, xvap); 773eda14cbcSMatt Macy start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize); 774eda14cbcSMatt Macy } 775eda14cbcSMatt Macy 776eda14cbcSMatt Macy /* 777eda14cbcSMatt Macy * Now stick on domain information if any on end 778eda14cbcSMatt Macy */ 779eda14cbcSMatt Macy 780eda14cbcSMatt Macy if (fuidp) 781eda14cbcSMatt Macy (void) zfs_log_fuid_domains(fuidp, start); 782eda14cbcSMatt Macy 783eda14cbcSMatt Macy itx->itx_sync = (zp->z_sync_cnt != 0); 784eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 785eda14cbcSMatt Macy } 786eda14cbcSMatt Macy 787eda14cbcSMatt Macy /* 788c03c5b1cSMartin Matuska * Handles TX_SETSAXATTR transactions. 789c03c5b1cSMartin Matuska */ 790c03c5b1cSMartin Matuska void 791c03c5b1cSMartin Matuska zfs_log_setsaxattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, 792c03c5b1cSMartin Matuska znode_t *zp, const char *name, const void *value, size_t size) 793c03c5b1cSMartin Matuska { 794c03c5b1cSMartin Matuska itx_t *itx; 795c03c5b1cSMartin Matuska lr_setsaxattr_t *lr; 796c03c5b1cSMartin Matuska size_t recsize = sizeof (lr_setsaxattr_t); 797c03c5b1cSMartin Matuska void *xattrstart; 798c03c5b1cSMartin Matuska int namelen; 799c03c5b1cSMartin Matuska 800c03c5b1cSMartin Matuska if (zil_replaying(zilog, tx) || zp->z_unlinked) 801c03c5b1cSMartin Matuska return; 802c03c5b1cSMartin Matuska 803c03c5b1cSMartin Matuska namelen = strlen(name) + 1; 804c03c5b1cSMartin Matuska recsize += (namelen + size); 805c03c5b1cSMartin Matuska itx = zil_itx_create(txtype, recsize); 806c03c5b1cSMartin Matuska lr = (lr_setsaxattr_t *)&itx->itx_lr; 807c03c5b1cSMartin Matuska lr->lr_foid = zp->z_id; 808c03c5b1cSMartin Matuska xattrstart = (char *)(lr + 1); 809da5137abSMartin Matuska memcpy(xattrstart, name, namelen); 810c03c5b1cSMartin Matuska if (value != NULL) { 811da5137abSMartin Matuska memcpy((char *)xattrstart + namelen, value, size); 812c03c5b1cSMartin Matuska lr->lr_size = size; 813c03c5b1cSMartin Matuska } else { 814c03c5b1cSMartin Matuska lr->lr_size = 0; 815c03c5b1cSMartin Matuska } 816c03c5b1cSMartin Matuska 817c03c5b1cSMartin Matuska itx->itx_sync = (zp->z_sync_cnt != 0); 818c03c5b1cSMartin Matuska zil_itx_assign(zilog, itx, tx); 819c03c5b1cSMartin Matuska } 820c03c5b1cSMartin Matuska 821c03c5b1cSMartin Matuska /* 822eda14cbcSMatt Macy * Handles TX_ACL transactions. 823eda14cbcSMatt Macy */ 824eda14cbcSMatt Macy void 825eda14cbcSMatt Macy zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp, 826eda14cbcSMatt Macy vsecattr_t *vsecp, zfs_fuid_info_t *fuidp) 827eda14cbcSMatt Macy { 828eda14cbcSMatt Macy itx_t *itx; 829eda14cbcSMatt Macy lr_acl_v0_t *lrv0; 830eda14cbcSMatt Macy lr_acl_t *lr; 831eda14cbcSMatt Macy int txtype; 832eda14cbcSMatt Macy int lrsize; 833eda14cbcSMatt Macy size_t txsize; 834eda14cbcSMatt Macy size_t aclbytes = vsecp->vsa_aclentsz; 835eda14cbcSMatt Macy 836eda14cbcSMatt Macy if (zil_replaying(zilog, tx) || zp->z_unlinked) 837eda14cbcSMatt Macy return; 838eda14cbcSMatt Macy 839eda14cbcSMatt Macy txtype = (ZTOZSB(zp)->z_version < ZPL_VERSION_FUID) ? 840eda14cbcSMatt Macy TX_ACL_V0 : TX_ACL; 841eda14cbcSMatt Macy 842eda14cbcSMatt Macy if (txtype == TX_ACL) 843eda14cbcSMatt Macy lrsize = sizeof (*lr); 844eda14cbcSMatt Macy else 845eda14cbcSMatt Macy lrsize = sizeof (*lrv0); 846eda14cbcSMatt Macy 847eda14cbcSMatt Macy txsize = lrsize + 848eda14cbcSMatt Macy ((txtype == TX_ACL) ? ZIL_ACE_LENGTH(aclbytes) : aclbytes) + 849eda14cbcSMatt Macy (fuidp ? fuidp->z_domain_str_sz : 0) + 850eda14cbcSMatt Macy sizeof (uint64_t) * (fuidp ? fuidp->z_fuid_cnt : 0); 851eda14cbcSMatt Macy 852eda14cbcSMatt Macy itx = zil_itx_create(txtype, txsize); 853eda14cbcSMatt Macy 854eda14cbcSMatt Macy lr = (lr_acl_t *)&itx->itx_lr; 855eda14cbcSMatt Macy lr->lr_foid = zp->z_id; 856eda14cbcSMatt Macy if (txtype == TX_ACL) { 857eda14cbcSMatt Macy lr->lr_acl_bytes = aclbytes; 858eda14cbcSMatt Macy lr->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0; 859eda14cbcSMatt Macy lr->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0; 860eda14cbcSMatt Macy if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS) 861eda14cbcSMatt Macy lr->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags; 862eda14cbcSMatt Macy else 863eda14cbcSMatt Macy lr->lr_acl_flags = 0; 864eda14cbcSMatt Macy } 865eda14cbcSMatt Macy lr->lr_aclcnt = (uint64_t)vsecp->vsa_aclcnt; 866eda14cbcSMatt Macy 867eda14cbcSMatt Macy if (txtype == TX_ACL_V0) { 868eda14cbcSMatt Macy lrv0 = (lr_acl_v0_t *)lr; 869da5137abSMartin Matuska memcpy(lrv0 + 1, vsecp->vsa_aclentp, aclbytes); 870eda14cbcSMatt Macy } else { 871eda14cbcSMatt Macy void *start = (ace_t *)(lr + 1); 872eda14cbcSMatt Macy 873da5137abSMartin Matuska memcpy(start, vsecp->vsa_aclentp, aclbytes); 874eda14cbcSMatt Macy 875eda14cbcSMatt Macy start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes); 876eda14cbcSMatt Macy 877eda14cbcSMatt Macy if (fuidp) { 878eda14cbcSMatt Macy start = zfs_log_fuid_ids(fuidp, start); 879eda14cbcSMatt Macy (void) zfs_log_fuid_domains(fuidp, start); 880eda14cbcSMatt Macy } 881eda14cbcSMatt Macy } 882eda14cbcSMatt Macy 883eda14cbcSMatt Macy itx->itx_sync = (zp->z_sync_cnt != 0); 884eda14cbcSMatt Macy zil_itx_assign(zilog, itx, tx); 885eda14cbcSMatt Macy } 886eda14cbcSMatt Macy 8872a58b312SMartin Matuska /* 8882a58b312SMartin Matuska * Handles TX_CLONE_RANGE transactions. 8892a58b312SMartin Matuska */ 8902a58b312SMartin Matuska void 8912a58b312SMartin Matuska zfs_log_clone_range(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, 8922a58b312SMartin Matuska uint64_t off, uint64_t len, uint64_t blksz, const blkptr_t *bps, 8932a58b312SMartin Matuska size_t nbps) 8942a58b312SMartin Matuska { 8952a58b312SMartin Matuska itx_t *itx; 8962a58b312SMartin Matuska lr_clone_range_t *lr; 8972a58b312SMartin Matuska uint64_t partlen, max_log_data; 8982a58b312SMartin Matuska size_t i, partnbps; 8992a58b312SMartin Matuska 9001959e122SPawel Jakub Dawidek if (zil_replaying(zilog, tx) || zp->z_unlinked) 9012a58b312SMartin Matuska return; 9022a58b312SMartin Matuska 9032a58b312SMartin Matuska max_log_data = zil_max_log_data(zilog, sizeof (lr_clone_range_t)); 9042a58b312SMartin Matuska 9052a58b312SMartin Matuska while (nbps > 0) { 9062a58b312SMartin Matuska partnbps = MIN(nbps, max_log_data / sizeof (bps[0])); 9072a58b312SMartin Matuska partlen = 0; 9082a58b312SMartin Matuska for (i = 0; i < partnbps; i++) { 9092a58b312SMartin Matuska partlen += BP_GET_LSIZE(&bps[i]); 9102a58b312SMartin Matuska } 9112a58b312SMartin Matuska partlen = MIN(partlen, len); 9122a58b312SMartin Matuska 9132a58b312SMartin Matuska itx = zil_itx_create(txtype, 9142a58b312SMartin Matuska sizeof (*lr) + sizeof (bps[0]) * partnbps); 9152a58b312SMartin Matuska lr = (lr_clone_range_t *)&itx->itx_lr; 9162a58b312SMartin Matuska lr->lr_foid = zp->z_id; 9172a58b312SMartin Matuska lr->lr_offset = off; 9182a58b312SMartin Matuska lr->lr_length = partlen; 9192a58b312SMartin Matuska lr->lr_blksz = blksz; 9202a58b312SMartin Matuska lr->lr_nbps = partnbps; 9212a58b312SMartin Matuska memcpy(lr->lr_bps, bps, sizeof (bps[0]) * partnbps); 9222a58b312SMartin Matuska 9232a58b312SMartin Matuska itx->itx_sync = (zp->z_sync_cnt != 0); 9242a58b312SMartin Matuska 9252a58b312SMartin Matuska zil_itx_assign(zilog, itx, tx); 9262a58b312SMartin Matuska 9272a58b312SMartin Matuska bps += partnbps; 9282a58b312SMartin Matuska ASSERT3U(nbps, >=, partnbps); 9292a58b312SMartin Matuska nbps -= partnbps; 9302a58b312SMartin Matuska off += partlen; 9312a58b312SMartin Matuska ASSERT3U(len, >=, partlen); 9322a58b312SMartin Matuska len -= partlen; 9332a58b312SMartin Matuska } 9342a58b312SMartin Matuska } 9352a58b312SMartin Matuska 936dbd5678dSMartin Matuska ZFS_MODULE_PARAM(zfs, zfs_, immediate_write_sz, S64, ZMOD_RW, 937eda14cbcSMatt Macy "Largest data block to write to zil"); 938