1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 572fc53bcSmarks * Common Development and Distribution License (the "License"). 672fc53bcSmarks * 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 /* 2291de656bSNeil Perrin * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23*9a686fbcSPaul Dagnelie * Copyright (c) 2013, 2015 by Delphix. All rights reserved. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #include <sys/types.h> 27fa9e4066Sahrens #include <sys/param.h> 28fa9e4066Sahrens #include <sys/systm.h> 29fa9e4066Sahrens #include <sys/sysmacros.h> 30fa9e4066Sahrens #include <sys/cmn_err.h> 31fa9e4066Sahrens #include <sys/kmem.h> 32fa9e4066Sahrens #include <sys/thread.h> 33fa9e4066Sahrens #include <sys/file.h> 34fa9e4066Sahrens #include <sys/fcntl.h> 35fa9e4066Sahrens #include <sys/vfs.h> 36fa9e4066Sahrens #include <sys/fs/zfs.h> 37fa9e4066Sahrens #include <sys/zfs_znode.h> 38fa9e4066Sahrens #include <sys/zfs_dir.h> 39fa9e4066Sahrens #include <sys/zfs_acl.h> 40da6c28aaSamw #include <sys/zfs_fuid.h> 41fa9e4066Sahrens #include <sys/spa.h> 42fa9e4066Sahrens #include <sys/zil.h> 43fa9e4066Sahrens #include <sys/byteorder.h> 44fa9e4066Sahrens #include <sys/stat.h> 45fa9e4066Sahrens #include <sys/mode.h> 46fa9e4066Sahrens #include <sys/acl.h> 47fa9e4066Sahrens #include <sys/atomic.h> 48fa9e4066Sahrens #include <sys/cred.h> 49fa9e4066Sahrens 50fa9e4066Sahrens /* 51fa9e4066Sahrens * Functions to replay ZFS intent log (ZIL) records 52fa9e4066Sahrens * The functions are called through a function vector (zfs_replay_vector) 53fa9e4066Sahrens * which is indexed by the transaction type. 54fa9e4066Sahrens */ 55fa9e4066Sahrens 56fa9e4066Sahrens static void 57fa9e4066Sahrens zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode, 58fa9e4066Sahrens uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid) 59fa9e4066Sahrens { 60fa9e4066Sahrens bzero(vap, sizeof (*vap)); 61fa9e4066Sahrens vap->va_mask = (uint_t)mask; 62fa9e4066Sahrens vap->va_type = IFTOVT(mode); 63fa9e4066Sahrens vap->va_mode = mode & MODEMASK; 64da6c28aaSamw vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; 65da6c28aaSamw vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; 6672fc53bcSmarks vap->va_rdev = zfs_cmpldev(rdev); 67fa9e4066Sahrens vap->va_nodeid = nodeid; 68fa9e4066Sahrens } 69fa9e4066Sahrens 70fa9e4066Sahrens /* ARGSUSED */ 71fa9e4066Sahrens static int 72fa9e4066Sahrens zfs_replay_error(zfsvfs_t *zfsvfs, lr_t *lr, boolean_t byteswap) 73fa9e4066Sahrens { 74be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 75fa9e4066Sahrens } 76fa9e4066Sahrens 77da6c28aaSamw static void 78da6c28aaSamw zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 79fa9e4066Sahrens { 80da6c28aaSamw xoptattr_t *xoap = NULL; 81da6c28aaSamw uint64_t *attrs; 82da6c28aaSamw uint64_t *crtime; 83569e6c63Smarks uint32_t *bitmap; 84da6c28aaSamw void *scanstamp; 85569e6c63Smarks int i; 86da6c28aaSamw 87da6c28aaSamw xvap->xva_vattr.va_mask |= AT_XVATTR; 88da6c28aaSamw if ((xoap = xva_getxoptattr(xvap)) == NULL) { 89da6c28aaSamw xvap->xva_vattr.va_mask &= ~AT_XVATTR; /* shouldn't happen */ 90da6c28aaSamw return; 91da6c28aaSamw } 92da6c28aaSamw 93da6c28aaSamw ASSERT(lrattr->lr_attr_masksize == xvap->xva_mapsize); 94569e6c63Smarks 95569e6c63Smarks bitmap = &lrattr->lr_attr_bitmap; 96569e6c63Smarks for (i = 0; i != lrattr->lr_attr_masksize; i++, bitmap++) 97569e6c63Smarks xvap->xva_reqattrmap[i] = *bitmap; 98569e6c63Smarks 99da6c28aaSamw attrs = (uint64_t *)(lrattr + lrattr->lr_attr_masksize - 1); 100da6c28aaSamw crtime = attrs + 1; 101da6c28aaSamw scanstamp = (caddr_t)(crtime + 2); 102da6c28aaSamw 103da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) 104da6c28aaSamw xoap->xoa_hidden = ((*attrs & XAT0_HIDDEN) != 0); 105da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) 106da6c28aaSamw xoap->xoa_system = ((*attrs & XAT0_SYSTEM) != 0); 107da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) 108da6c28aaSamw xoap->xoa_archive = ((*attrs & XAT0_ARCHIVE) != 0); 109da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_READONLY)) 110da6c28aaSamw xoap->xoa_readonly = ((*attrs & XAT0_READONLY) != 0); 111da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) 112da6c28aaSamw xoap->xoa_immutable = ((*attrs & XAT0_IMMUTABLE) != 0); 113da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) 114da6c28aaSamw xoap->xoa_nounlink = ((*attrs & XAT0_NOUNLINK) != 0); 115da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) 116da6c28aaSamw xoap->xoa_appendonly = ((*attrs & XAT0_APPENDONLY) != 0); 117da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) 118da6c28aaSamw xoap->xoa_nodump = ((*attrs & XAT0_NODUMP) != 0); 119da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) 120da6c28aaSamw xoap->xoa_opaque = ((*attrs & XAT0_OPAQUE) != 0); 121da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) 122da6c28aaSamw xoap->xoa_av_modified = ((*attrs & XAT0_AV_MODIFIED) != 0); 123da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) 124da6c28aaSamw xoap->xoa_av_quarantined = 125da6c28aaSamw ((*attrs & XAT0_AV_QUARANTINED) != 0); 126da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) 127da6c28aaSamw ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime); 128da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) 129da6c28aaSamw bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); 1307a286c47SDai Ngo if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) 1317a286c47SDai Ngo xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); 132fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) 133fd9ee8b5Sjoyce mcintosh xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0); 134fd9ee8b5Sjoyce mcintosh if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) 135fd9ee8b5Sjoyce mcintosh xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); 136da6c28aaSamw } 137da6c28aaSamw 138da6c28aaSamw static int 139da6c28aaSamw zfs_replay_domain_cnt(uint64_t uid, uint64_t gid) 140da6c28aaSamw { 141da6c28aaSamw uint64_t uid_idx; 142da6c28aaSamw uint64_t gid_idx; 143da6c28aaSamw int domcnt = 0; 144da6c28aaSamw 145da6c28aaSamw uid_idx = FUID_INDEX(uid); 146da6c28aaSamw gid_idx = FUID_INDEX(gid); 147da6c28aaSamw if (uid_idx) 148da6c28aaSamw domcnt++; 149da6c28aaSamw if (gid_idx > 0 && gid_idx != uid_idx) 150da6c28aaSamw domcnt++; 151da6c28aaSamw 152da6c28aaSamw return (domcnt); 153da6c28aaSamw } 154da6c28aaSamw 155da6c28aaSamw static void * 156da6c28aaSamw zfs_replay_fuid_domain_common(zfs_fuid_info_t *fuid_infop, void *start, 157da6c28aaSamw int domcnt) 158da6c28aaSamw { 159da6c28aaSamw int i; 160da6c28aaSamw 161da6c28aaSamw for (i = 0; i != domcnt; i++) { 162da6c28aaSamw fuid_infop->z_domain_table[i] = start; 163da6c28aaSamw start = (caddr_t)start + strlen(start) + 1; 164da6c28aaSamw } 165da6c28aaSamw 166da6c28aaSamw return (start); 167da6c28aaSamw } 168da6c28aaSamw 169da6c28aaSamw /* 170da6c28aaSamw * Set the uid/gid in the fuid_info structure. 171da6c28aaSamw */ 172da6c28aaSamw static void 173da6c28aaSamw zfs_replay_fuid_ugid(zfs_fuid_info_t *fuid_infop, uint64_t uid, uint64_t gid) 174da6c28aaSamw { 175da6c28aaSamw /* 176da6c28aaSamw * If owner or group are log specific FUIDs then slurp up 177da6c28aaSamw * domain information and build zfs_fuid_info_t 178da6c28aaSamw */ 179da6c28aaSamw if (IS_EPHEMERAL(uid)) 180da6c28aaSamw fuid_infop->z_fuid_owner = uid; 181da6c28aaSamw 182da6c28aaSamw if (IS_EPHEMERAL(gid)) 183da6c28aaSamw fuid_infop->z_fuid_group = gid; 184da6c28aaSamw } 185da6c28aaSamw 186da6c28aaSamw /* 187da6c28aaSamw * Load fuid domains into fuid_info_t 188da6c28aaSamw */ 189da6c28aaSamw static zfs_fuid_info_t * 190da6c28aaSamw zfs_replay_fuid_domain(void *buf, void **end, uint64_t uid, uint64_t gid) 191da6c28aaSamw { 192da6c28aaSamw int domcnt; 193da6c28aaSamw 194da6c28aaSamw zfs_fuid_info_t *fuid_infop; 195da6c28aaSamw 196da6c28aaSamw fuid_infop = zfs_fuid_info_alloc(); 197da6c28aaSamw 198da6c28aaSamw domcnt = zfs_replay_domain_cnt(uid, gid); 199da6c28aaSamw 200da6c28aaSamw if (domcnt == 0) 201da6c28aaSamw return (fuid_infop); 202da6c28aaSamw 203da6c28aaSamw fuid_infop->z_domain_table = 204da6c28aaSamw kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 205da6c28aaSamw 206da6c28aaSamw zfs_replay_fuid_ugid(fuid_infop, uid, gid); 207da6c28aaSamw 208da6c28aaSamw fuid_infop->z_domain_cnt = domcnt; 209da6c28aaSamw *end = zfs_replay_fuid_domain_common(fuid_infop, buf, domcnt); 210da6c28aaSamw return (fuid_infop); 211da6c28aaSamw } 212da6c28aaSamw 213da6c28aaSamw /* 214da6c28aaSamw * load zfs_fuid_t's and fuid_domains into fuid_info_t 215da6c28aaSamw */ 216da6c28aaSamw static zfs_fuid_info_t * 217da6c28aaSamw zfs_replay_fuids(void *start, void **end, int idcnt, int domcnt, uint64_t uid, 218da6c28aaSamw uint64_t gid) 219da6c28aaSamw { 220da6c28aaSamw uint64_t *log_fuid = (uint64_t *)start; 221da6c28aaSamw zfs_fuid_info_t *fuid_infop; 222da6c28aaSamw int i; 223da6c28aaSamw 224da6c28aaSamw fuid_infop = zfs_fuid_info_alloc(); 225da6c28aaSamw fuid_infop->z_domain_cnt = domcnt; 226da6c28aaSamw 227da6c28aaSamw fuid_infop->z_domain_table = 228da6c28aaSamw kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 229da6c28aaSamw 230da6c28aaSamw for (i = 0; i != idcnt; i++) { 231da6c28aaSamw zfs_fuid_t *zfuid; 232da6c28aaSamw 233da6c28aaSamw zfuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP); 234da6c28aaSamw zfuid->z_logfuid = *log_fuid; 235da6c28aaSamw zfuid->z_id = -1; 236da6c28aaSamw zfuid->z_domidx = 0; 237da6c28aaSamw list_insert_tail(&fuid_infop->z_fuids, zfuid); 238da6c28aaSamw log_fuid++; 239da6c28aaSamw } 240da6c28aaSamw 241da6c28aaSamw zfs_replay_fuid_ugid(fuid_infop, uid, gid); 242da6c28aaSamw 243da6c28aaSamw *end = zfs_replay_fuid_domain_common(fuid_infop, log_fuid, domcnt); 244da6c28aaSamw return (fuid_infop); 245da6c28aaSamw } 246da6c28aaSamw 247da6c28aaSamw static void 248da6c28aaSamw zfs_replay_swap_attrs(lr_attr_t *lrattr) 249da6c28aaSamw { 250da6c28aaSamw /* swap the lr_attr structure */ 251da6c28aaSamw byteswap_uint32_array(lrattr, sizeof (*lrattr)); 252da6c28aaSamw /* swap the bitmap */ 253569e6c63Smarks byteswap_uint32_array(lrattr + 1, (lrattr->lr_attr_masksize - 1) * 254569e6c63Smarks sizeof (uint32_t)); 255da6c28aaSamw /* swap the attributes, create time + 64 bit word for attributes */ 256569e6c63Smarks byteswap_uint64_array((caddr_t)(lrattr + 1) + (sizeof (uint32_t) * 257da6c28aaSamw (lrattr->lr_attr_masksize - 1)), 3 * sizeof (uint64_t)); 258da6c28aaSamw } 259da6c28aaSamw 260da6c28aaSamw /* 261da6c28aaSamw * Replay file create with optional ACL, xvattr information as well 262da6c28aaSamw * as option FUID information. 263da6c28aaSamw */ 264da6c28aaSamw static int 265da6c28aaSamw zfs_replay_create_acl(zfsvfs_t *zfsvfs, 266da6c28aaSamw lr_acl_create_t *lracl, boolean_t byteswap) 267da6c28aaSamw { 268da6c28aaSamw char *name = NULL; /* location determined later */ 269da6c28aaSamw lr_create_t *lr = (lr_create_t *)lracl; 270fa9e4066Sahrens znode_t *dzp; 271fa9e4066Sahrens vnode_t *vp = NULL; 272da6c28aaSamw xvattr_t xva; 273da6c28aaSamw int vflg = 0; 274da6c28aaSamw vsecattr_t vsec = { 0 }; 275da6c28aaSamw lr_attr_t *lrattr; 276da6c28aaSamw void *aclstart; 277da6c28aaSamw void *fuidstart; 278da6c28aaSamw size_t xvatlen = 0; 279da6c28aaSamw uint64_t txtype; 280fa9e4066Sahrens int error; 281fa9e4066Sahrens 2824a1f0cc9SMark Shellenbaum txtype = (lr->lr_common.lrc_txtype & ~TX_CI); 283da6c28aaSamw if (byteswap) { 284da6c28aaSamw byteswap_uint64_array(lracl, sizeof (*lracl)); 285da6c28aaSamw if (txtype == TX_CREATE_ACL_ATTR || 286da6c28aaSamw txtype == TX_MKDIR_ACL_ATTR) { 287569e6c63Smarks lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 288da6c28aaSamw zfs_replay_swap_attrs(lrattr); 289da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 290da6c28aaSamw } 291da6c28aaSamw 292da6c28aaSamw aclstart = (caddr_t)(lracl + 1) + xvatlen; 293da6c28aaSamw zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); 294da6c28aaSamw /* swap fuids */ 295da6c28aaSamw if (lracl->lr_fuidcnt) { 296da6c28aaSamw byteswap_uint64_array((caddr_t)aclstart + 297569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes), 298569e6c63Smarks lracl->lr_fuidcnt * sizeof (uint64_t)); 299da6c28aaSamw } 300da6c28aaSamw } 301fa9e4066Sahrens 302fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 303fa9e4066Sahrens return (error); 304fa9e4066Sahrens 305da6c28aaSamw xva_init(&xva); 306da6c28aaSamw zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 307fa9e4066Sahrens lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 308fa9e4066Sahrens 309fa9e4066Sahrens /* 310fa9e4066Sahrens * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 311fa9e4066Sahrens * eventually end up in zfs_mknode(), which assigns the object's 312fa9e4066Sahrens * creation time and generation number. The generic VOP_CREATE() 313fa9e4066Sahrens * doesn't have either concept, so we smuggle the values inside 314fa9e4066Sahrens * the vattr's otherwise unused va_ctime and va_nblocks fields. 315fa9e4066Sahrens */ 316da6c28aaSamw ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 317da6c28aaSamw xva.xva_vattr.va_nblocks = lr->lr_gen; 318da6c28aaSamw 319da6c28aaSamw error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 320da6c28aaSamw if (error != ENOENT) 321da6c28aaSamw goto bail; 322da6c28aaSamw 323da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 324da6c28aaSamw vflg |= FIGNORECASE; 3254a1f0cc9SMark Shellenbaum switch (txtype) { 326da6c28aaSamw case TX_CREATE_ACL: 327da6c28aaSamw aclstart = (caddr_t)(lracl + 1); 328569e6c63Smarks fuidstart = (caddr_t)aclstart + 329569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 330da6c28aaSamw zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 331da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 332da6c28aaSamw lr->lr_uid, lr->lr_gid); 333da6c28aaSamw /*FALLTHROUGH*/ 334da6c28aaSamw case TX_CREATE_ACL_ATTR: 335da6c28aaSamw if (name == NULL) { 336da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 337da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 338da6c28aaSamw xva.xva_vattr.va_mask |= AT_XVATTR; 339da6c28aaSamw zfs_replay_xvattr(lrattr, &xva); 340da6c28aaSamw } 341da6c28aaSamw vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 342da6c28aaSamw vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 343da6c28aaSamw vsec.vsa_aclcnt = lracl->lr_aclcnt; 344da6c28aaSamw vsec.vsa_aclentsz = lracl->lr_acl_bytes; 345da6c28aaSamw vsec.vsa_aclflags = lracl->lr_acl_flags; 3468436ade2Smarks if (zfsvfs->z_fuid_replay == NULL) { 347da6c28aaSamw fuidstart = (caddr_t)(lracl + 1) + xvatlen + 348569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 349da6c28aaSamw zfsvfs->z_fuid_replay = 350da6c28aaSamw zfs_replay_fuids(fuidstart, 351da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 352da6c28aaSamw lr->lr_uid, lr->lr_gid); 3538436ade2Smarks } 354da6c28aaSamw 355da6c28aaSamw error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 356da6c28aaSamw 0, 0, &vp, kcred, vflg, NULL, &vsec); 357da6c28aaSamw break; 358da6c28aaSamw case TX_MKDIR_ACL: 359da6c28aaSamw aclstart = (caddr_t)(lracl + 1); 360569e6c63Smarks fuidstart = (caddr_t)aclstart + 361569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 362da6c28aaSamw zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 363da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 364da6c28aaSamw lr->lr_uid, lr->lr_gid); 365da6c28aaSamw /*FALLTHROUGH*/ 366da6c28aaSamw case TX_MKDIR_ACL_ATTR: 367da6c28aaSamw if (name == NULL) { 368da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 369da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 370da6c28aaSamw zfs_replay_xvattr(lrattr, &xva); 371da6c28aaSamw } 372da6c28aaSamw vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 373da6c28aaSamw vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 374da6c28aaSamw vsec.vsa_aclcnt = lracl->lr_aclcnt; 375da6c28aaSamw vsec.vsa_aclentsz = lracl->lr_acl_bytes; 376da6c28aaSamw vsec.vsa_aclflags = lracl->lr_acl_flags; 3778436ade2Smarks if (zfsvfs->z_fuid_replay == NULL) { 378da6c28aaSamw fuidstart = (caddr_t)(lracl + 1) + xvatlen + 379569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 380da6c28aaSamw zfsvfs->z_fuid_replay = 381da6c28aaSamw zfs_replay_fuids(fuidstart, 382da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 383da6c28aaSamw lr->lr_uid, lr->lr_gid); 3848436ade2Smarks } 385da6c28aaSamw error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, 386da6c28aaSamw &vp, kcred, NULL, vflg, &vsec); 387da6c28aaSamw break; 388da6c28aaSamw default: 389be6fd75aSMatthew Ahrens error = SET_ERROR(ENOTSUP); 390da6c28aaSamw } 391da6c28aaSamw 392da6c28aaSamw bail: 393da6c28aaSamw if (error == 0 && vp != NULL) 394da6c28aaSamw VN_RELE(vp); 395da6c28aaSamw 396da6c28aaSamw VN_RELE(ZTOV(dzp)); 397da6c28aaSamw 3984a1f0cc9SMark Shellenbaum if (zfsvfs->z_fuid_replay) 399da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 400da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 401da6c28aaSamw 402da6c28aaSamw return (error); 403da6c28aaSamw } 404da6c28aaSamw 405da6c28aaSamw static int 406da6c28aaSamw zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) 407da6c28aaSamw { 408da6c28aaSamw char *name = NULL; /* location determined later */ 409da6c28aaSamw char *link; /* symlink content follows name */ 410da6c28aaSamw znode_t *dzp; 411da6c28aaSamw vnode_t *vp = NULL; 412da6c28aaSamw xvattr_t xva; 413da6c28aaSamw int vflg = 0; 414da6c28aaSamw size_t lrsize = sizeof (lr_create_t); 415da6c28aaSamw lr_attr_t *lrattr; 416da6c28aaSamw void *start; 417da6c28aaSamw size_t xvatlen; 418da6c28aaSamw uint64_t txtype; 419da6c28aaSamw int error; 420da6c28aaSamw 4214a1f0cc9SMark Shellenbaum txtype = (lr->lr_common.lrc_txtype & ~TX_CI); 422da6c28aaSamw if (byteswap) { 423da6c28aaSamw byteswap_uint64_array(lr, sizeof (*lr)); 424da6c28aaSamw if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) 425da6c28aaSamw zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 426da6c28aaSamw } 427da6c28aaSamw 428da6c28aaSamw 429da6c28aaSamw if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 430da6c28aaSamw return (error); 431da6c28aaSamw 432da6c28aaSamw xva_init(&xva); 433da6c28aaSamw zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 434da6c28aaSamw lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 435da6c28aaSamw 436da6c28aaSamw /* 437da6c28aaSamw * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 438da6c28aaSamw * eventually end up in zfs_mknode(), which assigns the object's 439da6c28aaSamw * creation time and generation number. The generic VOP_CREATE() 440da6c28aaSamw * doesn't have either concept, so we smuggle the values inside 441da6c28aaSamw * the vattr's otherwise unused va_ctime and va_nblocks fields. 442da6c28aaSamw */ 443da6c28aaSamw ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 444da6c28aaSamw xva.xva_vattr.va_nblocks = lr->lr_gen; 445fa9e4066Sahrens 446758f6e0bSgw25295 error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 447758f6e0bSgw25295 if (error != ENOENT) 448758f6e0bSgw25295 goto out; 449758f6e0bSgw25295 450da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 451da6c28aaSamw vflg |= FIGNORECASE; 452da6c28aaSamw 453da6c28aaSamw /* 454da6c28aaSamw * Symlinks don't have fuid info, and CIFS never creates 455da6c28aaSamw * symlinks. 456da6c28aaSamw * 457da6c28aaSamw * The _ATTR versions will grab the fuid info in their subcases. 458da6c28aaSamw */ 459da6c28aaSamw if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK && 460da6c28aaSamw (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR && 461da6c28aaSamw (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) { 462da6c28aaSamw start = (lr + 1); 463da6c28aaSamw zfsvfs->z_fuid_replay = 464da6c28aaSamw zfs_replay_fuid_domain(start, &start, 465da6c28aaSamw lr->lr_uid, lr->lr_gid); 466da6c28aaSamw } 467da6c28aaSamw 4684a1f0cc9SMark Shellenbaum switch (txtype) { 469da6c28aaSamw case TX_CREATE_ATTR: 470da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 471da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 472da6c28aaSamw zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 473da6c28aaSamw start = (caddr_t)(lr + 1) + xvatlen; 474da6c28aaSamw zfsvfs->z_fuid_replay = 475da6c28aaSamw zfs_replay_fuid_domain(start, &start, 476da6c28aaSamw lr->lr_uid, lr->lr_gid); 477da6c28aaSamw name = (char *)start; 478da6c28aaSamw 479da6c28aaSamw /*FALLTHROUGH*/ 480fa9e4066Sahrens case TX_CREATE: 481da6c28aaSamw if (name == NULL) 482da6c28aaSamw name = (char *)start; 483da6c28aaSamw 484da6c28aaSamw error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 485da6c28aaSamw 0, 0, &vp, kcred, vflg, NULL, NULL); 486fa9e4066Sahrens break; 487da6c28aaSamw case TX_MKDIR_ATTR: 488da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 489da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 490da6c28aaSamw zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 491da6c28aaSamw start = (caddr_t)(lr + 1) + xvatlen; 492da6c28aaSamw zfsvfs->z_fuid_replay = 493da6c28aaSamw zfs_replay_fuid_domain(start, &start, 494da6c28aaSamw lr->lr_uid, lr->lr_gid); 495da6c28aaSamw name = (char *)start; 496da6c28aaSamw 497da6c28aaSamw /*FALLTHROUGH*/ 498fa9e4066Sahrens case TX_MKDIR: 499da6c28aaSamw if (name == NULL) 500da6c28aaSamw name = (char *)(lr + 1); 501da6c28aaSamw 502da6c28aaSamw error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, 503da6c28aaSamw &vp, kcred, NULL, vflg, NULL); 504fa9e4066Sahrens break; 505fa9e4066Sahrens case TX_MKXATTR: 506da6c28aaSamw error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &vp, kcred); 507fa9e4066Sahrens break; 508fa9e4066Sahrens case TX_SYMLINK: 509da6c28aaSamw name = (char *)(lr + 1); 510fa9e4066Sahrens link = name + strlen(name) + 1; 511da6c28aaSamw error = VOP_SYMLINK(ZTOV(dzp), name, &xva.xva_vattr, 512da6c28aaSamw link, kcred, NULL, vflg); 513fa9e4066Sahrens break; 514fa9e4066Sahrens default: 515be6fd75aSMatthew Ahrens error = SET_ERROR(ENOTSUP); 516fa9e4066Sahrens } 517fa9e4066Sahrens 518758f6e0bSgw25295 out: 519fa9e4066Sahrens if (error == 0 && vp != NULL) 520fa9e4066Sahrens VN_RELE(vp); 521fa9e4066Sahrens 522fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 523fa9e4066Sahrens 524da6c28aaSamw if (zfsvfs->z_fuid_replay) 525da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 526da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 527fa9e4066Sahrens return (error); 528fa9e4066Sahrens } 529fa9e4066Sahrens 530fa9e4066Sahrens static int 531fa9e4066Sahrens zfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap) 532fa9e4066Sahrens { 533fa9e4066Sahrens char *name = (char *)(lr + 1); /* name follows lr_remove_t */ 534fa9e4066Sahrens znode_t *dzp; 535fa9e4066Sahrens int error; 536da6c28aaSamw int vflg = 0; 537fa9e4066Sahrens 538fa9e4066Sahrens if (byteswap) 539fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 540fa9e4066Sahrens 541fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 542fa9e4066Sahrens return (error); 543fa9e4066Sahrens 544da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 545da6c28aaSamw vflg |= FIGNORECASE; 546da6c28aaSamw 547fa9e4066Sahrens switch ((int)lr->lr_common.lrc_txtype) { 548fa9e4066Sahrens case TX_REMOVE: 549da6c28aaSamw error = VOP_REMOVE(ZTOV(dzp), name, kcred, NULL, vflg); 550fa9e4066Sahrens break; 551fa9e4066Sahrens case TX_RMDIR: 552da6c28aaSamw error = VOP_RMDIR(ZTOV(dzp), name, NULL, kcred, NULL, vflg); 553fa9e4066Sahrens break; 554fa9e4066Sahrens default: 555be6fd75aSMatthew Ahrens error = SET_ERROR(ENOTSUP); 556fa9e4066Sahrens } 557fa9e4066Sahrens 558fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 559fa9e4066Sahrens 560fa9e4066Sahrens return (error); 561fa9e4066Sahrens } 562fa9e4066Sahrens 563fa9e4066Sahrens static int 564fa9e4066Sahrens zfs_replay_link(zfsvfs_t *zfsvfs, lr_link_t *lr, boolean_t byteswap) 565fa9e4066Sahrens { 566fa9e4066Sahrens char *name = (char *)(lr + 1); /* name follows lr_link_t */ 567fa9e4066Sahrens znode_t *dzp, *zp; 568fa9e4066Sahrens int error; 569da6c28aaSamw int vflg = 0; 570fa9e4066Sahrens 571fa9e4066Sahrens if (byteswap) 572fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 573fa9e4066Sahrens 574fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 575fa9e4066Sahrens return (error); 576fa9e4066Sahrens 577fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_link_obj, &zp)) != 0) { 578fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 579fa9e4066Sahrens return (error); 580fa9e4066Sahrens } 581fa9e4066Sahrens 582da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 583da6c28aaSamw vflg |= FIGNORECASE; 584da6c28aaSamw 585da6c28aaSamw error = VOP_LINK(ZTOV(dzp), ZTOV(zp), name, kcred, NULL, vflg); 586fa9e4066Sahrens 587fa9e4066Sahrens VN_RELE(ZTOV(zp)); 588fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 589fa9e4066Sahrens 590fa9e4066Sahrens return (error); 591fa9e4066Sahrens } 592fa9e4066Sahrens 593fa9e4066Sahrens static int 594fa9e4066Sahrens zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap) 595fa9e4066Sahrens { 596fa9e4066Sahrens char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ 597fa9e4066Sahrens char *tname = sname + strlen(sname) + 1; 598fa9e4066Sahrens znode_t *sdzp, *tdzp; 599fa9e4066Sahrens int error; 600da6c28aaSamw int vflg = 0; 601fa9e4066Sahrens 602fa9e4066Sahrens if (byteswap) 603fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 604fa9e4066Sahrens 605fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) 606fa9e4066Sahrens return (error); 607fa9e4066Sahrens 608fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { 609fa9e4066Sahrens VN_RELE(ZTOV(sdzp)); 610fa9e4066Sahrens return (error); 611fa9e4066Sahrens } 612fa9e4066Sahrens 613da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 614da6c28aaSamw vflg |= FIGNORECASE; 615da6c28aaSamw 616da6c28aaSamw error = VOP_RENAME(ZTOV(sdzp), sname, ZTOV(tdzp), tname, kcred, 617da6c28aaSamw NULL, vflg); 618fa9e4066Sahrens 619fa9e4066Sahrens VN_RELE(ZTOV(tdzp)); 620fa9e4066Sahrens VN_RELE(ZTOV(sdzp)); 621fa9e4066Sahrens 622fa9e4066Sahrens return (error); 623fa9e4066Sahrens } 624fa9e4066Sahrens 625fa9e4066Sahrens static int 626fa9e4066Sahrens zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 627fa9e4066Sahrens { 628fa9e4066Sahrens char *data = (char *)(lr + 1); /* data follows lr_write_t */ 629fa9e4066Sahrens znode_t *zp; 630fa9e4066Sahrens int error; 631fa9e4066Sahrens ssize_t resid; 632c0e50c98SNeil Perrin uint64_t eod, offset, length; 633975c32a0SNeil Perrin 634975c32a0SNeil Perrin if (byteswap) 635975c32a0SNeil Perrin byteswap_uint64_array(lr, sizeof (*lr)); 636975c32a0SNeil Perrin 637975c32a0SNeil Perrin if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 638975c32a0SNeil Perrin /* 639975c32a0SNeil Perrin * As we can log writes out of order, it's possible the 640975c32a0SNeil Perrin * file has been removed. In this case just drop the write 641975c32a0SNeil Perrin * and return success. 642975c32a0SNeil Perrin */ 643975c32a0SNeil Perrin if (error == ENOENT) 644975c32a0SNeil Perrin error = 0; 645975c32a0SNeil Perrin return (error); 646975c32a0SNeil Perrin } 647b24ab676SJeff Bonwick 648b24ab676SJeff Bonwick offset = lr->lr_offset; 649b24ab676SJeff Bonwick length = lr->lr_length; 650b24ab676SJeff Bonwick eod = offset + length; /* end of data for this write */ 651b24ab676SJeff Bonwick 652c0e50c98SNeil Perrin /* 653c0e50c98SNeil Perrin * This may be a write from a dmu_sync() for a whole block, 654c0e50c98SNeil Perrin * and may extend beyond the current end of the file. 655c0e50c98SNeil Perrin * We can't just replay what was written for this TX_WRITE as 656c0e50c98SNeil Perrin * a future TX_WRITE2 may extend the eof and the data for that 657c0e50c98SNeil Perrin * write needs to be there. So we write the whole block and 658c0e50c98SNeil Perrin * reduce the eof. This needs to be done within the single dmu 659c0e50c98SNeil Perrin * transaction created within vn_rdwr -> zfs_write. So a possible 660c0e50c98SNeil Perrin * new end of file is passed through in zfsvfs->z_replay_eof 661c0e50c98SNeil Perrin */ 662c0e50c98SNeil Perrin 663c0e50c98SNeil Perrin zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */ 664975c32a0SNeil Perrin 665b24ab676SJeff Bonwick /* If it's a dmu_sync() block, write the whole block */ 666b24ab676SJeff Bonwick if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { 667b24ab676SJeff Bonwick uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr); 668b24ab676SJeff Bonwick if (length < blocksize) { 669b24ab676SJeff Bonwick offset -= offset % blocksize; 670b24ab676SJeff Bonwick length = blocksize; 671b24ab676SJeff Bonwick } 672c0e50c98SNeil Perrin if (zp->z_size < eod) 673c0e50c98SNeil Perrin zfsvfs->z_replay_eof = eod; 674b24ab676SJeff Bonwick } 675975c32a0SNeil Perrin 676b24ab676SJeff Bonwick error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset, 677b24ab676SJeff Bonwick UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); 678975c32a0SNeil Perrin 679975c32a0SNeil Perrin VN_RELE(ZTOV(zp)); 680c0e50c98SNeil Perrin zfsvfs->z_replay_eof = 0; /* safety */ 681975c32a0SNeil Perrin 682975c32a0SNeil Perrin return (error); 683975c32a0SNeil Perrin } 684975c32a0SNeil Perrin 685975c32a0SNeil Perrin /* 686975c32a0SNeil Perrin * TX_WRITE2 are only generated when dmu_sync() returns EALREADY 687975c32a0SNeil Perrin * meaning the pool block is already being synced. So now that we always write 688975c32a0SNeil Perrin * out full blocks, all we have to do is expand the eof if 689975c32a0SNeil Perrin * the file is grown. 690975c32a0SNeil Perrin */ 691975c32a0SNeil Perrin static int 692975c32a0SNeil Perrin zfs_replay_write2(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 693975c32a0SNeil Perrin { 694975c32a0SNeil Perrin znode_t *zp; 695975c32a0SNeil Perrin int error; 696975c32a0SNeil Perrin uint64_t end; 697fa9e4066Sahrens 698fa9e4066Sahrens if (byteswap) 699fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 700fa9e4066Sahrens 701b24ab676SJeff Bonwick if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 702fa9e4066Sahrens return (error); 703fa9e4066Sahrens 704c0e50c98SNeil Perrin top: 705975c32a0SNeil Perrin end = lr->lr_offset + lr->lr_length; 706c0e50c98SNeil Perrin if (end > zp->z_size) { 707c0e50c98SNeil Perrin dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 708c0e50c98SNeil Perrin 7090a586ceaSMark Shellenbaum zp->z_size = end; 710c0e50c98SNeil Perrin dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 711c0e50c98SNeil Perrin error = dmu_tx_assign(tx, TXG_WAIT); 712c0e50c98SNeil Perrin if (error) { 713c0e50c98SNeil Perrin VN_RELE(ZTOV(zp)); 714c0e50c98SNeil Perrin if (error == ERESTART) { 715c0e50c98SNeil Perrin dmu_tx_wait(tx); 716c0e50c98SNeil Perrin dmu_tx_abort(tx); 717c0e50c98SNeil Perrin goto top; 718c0e50c98SNeil Perrin } 719c0e50c98SNeil Perrin dmu_tx_abort(tx); 720c0e50c98SNeil Perrin return (error); 721c0e50c98SNeil Perrin } 722c0e50c98SNeil Perrin (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), 723c0e50c98SNeil Perrin (void *)&zp->z_size, sizeof (uint64_t), tx); 724c0e50c98SNeil Perrin 725c0e50c98SNeil Perrin /* Ensure the replayed seq is updated */ 726c0e50c98SNeil Perrin (void) zil_replaying(zfsvfs->z_log, tx); 727c0e50c98SNeil Perrin 728c0e50c98SNeil Perrin dmu_tx_commit(tx); 729c0e50c98SNeil Perrin } 730fa9e4066Sahrens 731fa9e4066Sahrens VN_RELE(ZTOV(zp)); 732fa9e4066Sahrens 733fa9e4066Sahrens return (error); 734fa9e4066Sahrens } 735fa9e4066Sahrens 736fa9e4066Sahrens static int 737fa9e4066Sahrens zfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap) 738fa9e4066Sahrens { 739fa9e4066Sahrens znode_t *zp; 740fa9e4066Sahrens flock64_t fl; 741fa9e4066Sahrens int error; 742fa9e4066Sahrens 743fa9e4066Sahrens if (byteswap) 744fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 745fa9e4066Sahrens 746b24ab676SJeff Bonwick if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 747fa9e4066Sahrens return (error); 748fa9e4066Sahrens 749fa9e4066Sahrens bzero(&fl, sizeof (fl)); 750fa9e4066Sahrens fl.l_type = F_WRLCK; 751fa9e4066Sahrens fl.l_whence = 0; 752fa9e4066Sahrens fl.l_start = lr->lr_offset; 753fa9e4066Sahrens fl.l_len = lr->lr_length; 754fa9e4066Sahrens 755fa9e4066Sahrens error = VOP_SPACE(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX, 756fa9e4066Sahrens lr->lr_offset, kcred, NULL); 757fa9e4066Sahrens 758fa9e4066Sahrens VN_RELE(ZTOV(zp)); 759fa9e4066Sahrens 760fa9e4066Sahrens return (error); 761fa9e4066Sahrens } 762fa9e4066Sahrens 763fa9e4066Sahrens static int 764fa9e4066Sahrens zfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap) 765fa9e4066Sahrens { 766fa9e4066Sahrens znode_t *zp; 767da6c28aaSamw xvattr_t xva; 768da6c28aaSamw vattr_t *vap = &xva.xva_vattr; 769fa9e4066Sahrens int error; 770da6c28aaSamw void *start; 771fa9e4066Sahrens 772da6c28aaSamw xva_init(&xva); 773da6c28aaSamw if (byteswap) { 774fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 775fa9e4066Sahrens 776da6c28aaSamw if ((lr->lr_mask & AT_XVATTR) && 777da6c28aaSamw zfsvfs->z_version >= ZPL_VERSION_INITIAL) 778da6c28aaSamw zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 779da6c28aaSamw } 780da6c28aaSamw 781b24ab676SJeff Bonwick if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 782fa9e4066Sahrens return (error); 783fa9e4066Sahrens 784da6c28aaSamw zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, 785fa9e4066Sahrens lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); 786fa9e4066Sahrens 787da6c28aaSamw vap->va_size = lr->lr_size; 788da6c28aaSamw ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); 789da6c28aaSamw ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); 790fa9e4066Sahrens 791da6c28aaSamw /* 792da6c28aaSamw * Fill in xvattr_t portions if necessary. 793da6c28aaSamw */ 794fa9e4066Sahrens 795da6c28aaSamw start = (lr_setattr_t *)(lr + 1); 796da6c28aaSamw if (vap->va_mask & AT_XVATTR) { 797da6c28aaSamw zfs_replay_xvattr((lr_attr_t *)start, &xva); 798da6c28aaSamw start = (caddr_t)start + 799da6c28aaSamw ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); 800da6c28aaSamw } else 801da6c28aaSamw xva.xva_vattr.va_mask &= ~AT_XVATTR; 802da6c28aaSamw 803da6c28aaSamw zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, 804da6c28aaSamw lr->lr_uid, lr->lr_gid); 805da6c28aaSamw 806da6c28aaSamw error = VOP_SETATTR(ZTOV(zp), vap, 0, kcred, NULL); 807da6c28aaSamw 808da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 809da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 810fa9e4066Sahrens VN_RELE(ZTOV(zp)); 811fa9e4066Sahrens 812fa9e4066Sahrens return (error); 813fa9e4066Sahrens } 814fa9e4066Sahrens 815fa9e4066Sahrens static int 816da6c28aaSamw zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap) 817fa9e4066Sahrens { 818fa9e4066Sahrens ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */ 819fa9e4066Sahrens vsecattr_t vsa; 820fa9e4066Sahrens znode_t *zp; 821fa9e4066Sahrens int error; 822fa9e4066Sahrens 823569e6c63Smarks if (byteswap) { 824569e6c63Smarks byteswap_uint64_array(lr, sizeof (*lr)); 825569e6c63Smarks zfs_oldace_byteswap(ace, lr->lr_aclcnt); 826569e6c63Smarks } 827569e6c63Smarks 828b24ab676SJeff Bonwick if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 829fa9e4066Sahrens return (error); 830fa9e4066Sahrens 831fa9e4066Sahrens bzero(&vsa, sizeof (vsa)); 832fa9e4066Sahrens vsa.vsa_mask = VSA_ACE | VSA_ACECNT; 833fa9e4066Sahrens vsa.vsa_aclcnt = lr->lr_aclcnt; 83431e69ea4Smarks vsa.vsa_aclentsz = sizeof (ace_t) * vsa.vsa_aclcnt; 83531e69ea4Smarks vsa.vsa_aclflags = 0; 836fa9e4066Sahrens vsa.vsa_aclentp = ace; 837fa9e4066Sahrens 838da6c28aaSamw error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); 839fa9e4066Sahrens 840fa9e4066Sahrens VN_RELE(ZTOV(zp)); 841fa9e4066Sahrens 842fa9e4066Sahrens return (error); 843fa9e4066Sahrens } 844fa9e4066Sahrens 845fa9e4066Sahrens /* 846da6c28aaSamw * Replaying ACLs is complicated by FUID support. 847da6c28aaSamw * The log record may contain some optional data 848da6c28aaSamw * to be used for replaying FUID's. These pieces 849da6c28aaSamw * are the actual FUIDs that were created initially. 850da6c28aaSamw * The FUID table index may no longer be valid and 851da6c28aaSamw * during zfs_create() a new index may be assigned. 852da6c28aaSamw * Because of this the log will contain the original 853da6c28aaSamw * doman+rid in order to create a new FUID. 854da6c28aaSamw * 855da6c28aaSamw * The individual ACEs may contain an ephemeral uid/gid which is no 856da6c28aaSamw * longer valid and will need to be replaced with an actual FUID. 857da6c28aaSamw * 858da6c28aaSamw */ 859da6c28aaSamw static int 860da6c28aaSamw zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap) 861da6c28aaSamw { 862da6c28aaSamw ace_t *ace = (ace_t *)(lr + 1); 863da6c28aaSamw vsecattr_t vsa; 864da6c28aaSamw znode_t *zp; 865da6c28aaSamw int error; 866da6c28aaSamw 867569e6c63Smarks if (byteswap) { 868569e6c63Smarks byteswap_uint64_array(lr, sizeof (*lr)); 869569e6c63Smarks zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE); 870569e6c63Smarks if (lr->lr_fuidcnt) { 871569e6c63Smarks byteswap_uint64_array((caddr_t)ace + 872569e6c63Smarks ZIL_ACE_LENGTH(lr->lr_acl_bytes), 873569e6c63Smarks lr->lr_fuidcnt * sizeof (uint64_t)); 874569e6c63Smarks } 875569e6c63Smarks } 876569e6c63Smarks 877b24ab676SJeff Bonwick if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 878da6c28aaSamw return (error); 879da6c28aaSamw 880da6c28aaSamw bzero(&vsa, sizeof (vsa)); 881da6c28aaSamw vsa.vsa_mask = VSA_ACE | VSA_ACECNT | VSA_ACE_ACLFLAGS; 882da6c28aaSamw vsa.vsa_aclcnt = lr->lr_aclcnt; 883da6c28aaSamw vsa.vsa_aclentp = ace; 884da6c28aaSamw vsa.vsa_aclentsz = lr->lr_acl_bytes; 885da6c28aaSamw vsa.vsa_aclflags = lr->lr_acl_flags; 886da6c28aaSamw 887da6c28aaSamw if (lr->lr_fuidcnt) { 888569e6c63Smarks void *fuidstart = (caddr_t)ace + 889569e6c63Smarks ZIL_ACE_LENGTH(lr->lr_acl_bytes); 890da6c28aaSamw 891da6c28aaSamw zfsvfs->z_fuid_replay = 892da6c28aaSamw zfs_replay_fuids(fuidstart, &fuidstart, 893da6c28aaSamw lr->lr_fuidcnt, lr->lr_domcnt, 0, 0); 894da6c28aaSamw } 895da6c28aaSamw 896da6c28aaSamw error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); 897da6c28aaSamw 898da6c28aaSamw if (zfsvfs->z_fuid_replay) 899da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 900da6c28aaSamw 901da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 902da6c28aaSamw VN_RELE(ZTOV(zp)); 903da6c28aaSamw 904da6c28aaSamw return (error); 905da6c28aaSamw } 906da6c28aaSamw 907da6c28aaSamw /* 908fa9e4066Sahrens * Callback vectors for replaying records 909fa9e4066Sahrens */ 910fa9e4066Sahrens zil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE] = { 911fa9e4066Sahrens zfs_replay_error, /* 0 no such transaction type */ 912fa9e4066Sahrens zfs_replay_create, /* TX_CREATE */ 913fa9e4066Sahrens zfs_replay_create, /* TX_MKDIR */ 914fa9e4066Sahrens zfs_replay_create, /* TX_MKXATTR */ 915fa9e4066Sahrens zfs_replay_create, /* TX_SYMLINK */ 916fa9e4066Sahrens zfs_replay_remove, /* TX_REMOVE */ 917fa9e4066Sahrens zfs_replay_remove, /* TX_RMDIR */ 918fa9e4066Sahrens zfs_replay_link, /* TX_LINK */ 919fa9e4066Sahrens zfs_replay_rename, /* TX_RENAME */ 920fa9e4066Sahrens zfs_replay_write, /* TX_WRITE */ 921fa9e4066Sahrens zfs_replay_truncate, /* TX_TRUNCATE */ 922fa9e4066Sahrens zfs_replay_setattr, /* TX_SETATTR */ 923da6c28aaSamw zfs_replay_acl_v0, /* TX_ACL_V0 */ 924fa9e4066Sahrens zfs_replay_acl, /* TX_ACL */ 925da6c28aaSamw zfs_replay_create_acl, /* TX_CREATE_ACL */ 926da6c28aaSamw zfs_replay_create, /* TX_CREATE_ATTR */ 927da6c28aaSamw zfs_replay_create_acl, /* TX_CREATE_ACL_ATTR */ 928da6c28aaSamw zfs_replay_create_acl, /* TX_MKDIR_ACL */ 929da6c28aaSamw zfs_replay_create, /* TX_MKDIR_ATTR */ 930da6c28aaSamw zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */ 931975c32a0SNeil Perrin zfs_replay_write2, /* TX_WRITE2 */ 932fa9e4066Sahrens }; 933