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 /* 22758f6e0bSgw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/types.h> 29fa9e4066Sahrens #include <sys/param.h> 30fa9e4066Sahrens #include <sys/systm.h> 31fa9e4066Sahrens #include <sys/sysmacros.h> 32fa9e4066Sahrens #include <sys/cmn_err.h> 33fa9e4066Sahrens #include <sys/kmem.h> 34fa9e4066Sahrens #include <sys/thread.h> 35fa9e4066Sahrens #include <sys/file.h> 36fa9e4066Sahrens #include <sys/fcntl.h> 37fa9e4066Sahrens #include <sys/vfs.h> 38fa9e4066Sahrens #include <sys/fs/zfs.h> 39fa9e4066Sahrens #include <sys/zfs_znode.h> 40fa9e4066Sahrens #include <sys/zfs_dir.h> 41fa9e4066Sahrens #include <sys/zfs_acl.h> 42da6c28aaSamw #include <sys/zfs_fuid.h> 43fa9e4066Sahrens #include <sys/spa.h> 44fa9e4066Sahrens #include <sys/zil.h> 45fa9e4066Sahrens #include <sys/byteorder.h> 46fa9e4066Sahrens #include <sys/stat.h> 47fa9e4066Sahrens #include <sys/mode.h> 48fa9e4066Sahrens #include <sys/acl.h> 49fa9e4066Sahrens #include <sys/atomic.h> 50fa9e4066Sahrens #include <sys/cred.h> 51fa9e4066Sahrens 52fa9e4066Sahrens /* 53fa9e4066Sahrens * Functions to replay ZFS intent log (ZIL) records 54fa9e4066Sahrens * The functions are called through a function vector (zfs_replay_vector) 55fa9e4066Sahrens * which is indexed by the transaction type. 56fa9e4066Sahrens */ 57fa9e4066Sahrens 58fa9e4066Sahrens static void 59fa9e4066Sahrens zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode, 60fa9e4066Sahrens uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid) 61fa9e4066Sahrens { 62fa9e4066Sahrens bzero(vap, sizeof (*vap)); 63fa9e4066Sahrens vap->va_mask = (uint_t)mask; 64fa9e4066Sahrens vap->va_type = IFTOVT(mode); 65fa9e4066Sahrens vap->va_mode = mode & MODEMASK; 66da6c28aaSamw vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; 67da6c28aaSamw vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; 6872fc53bcSmarks vap->va_rdev = zfs_cmpldev(rdev); 69fa9e4066Sahrens vap->va_nodeid = nodeid; 70fa9e4066Sahrens } 71fa9e4066Sahrens 72fa9e4066Sahrens /* ARGSUSED */ 73fa9e4066Sahrens static int 74fa9e4066Sahrens zfs_replay_error(zfsvfs_t *zfsvfs, lr_t *lr, boolean_t byteswap) 75fa9e4066Sahrens { 76fa9e4066Sahrens return (ENOTSUP); 77fa9e4066Sahrens } 78fa9e4066Sahrens 79da6c28aaSamw static void 80da6c28aaSamw zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 81da6c28aaSamw { 82da6c28aaSamw xoptattr_t *xoap = NULL; 83da6c28aaSamw uint64_t *attrs; 84da6c28aaSamw uint64_t *crtime; 85*569e6c63Smarks uint32_t *bitmap; 86da6c28aaSamw void *scanstamp; 87*569e6c63Smarks int i; 88da6c28aaSamw 89da6c28aaSamw xvap->xva_vattr.va_mask |= AT_XVATTR; 90da6c28aaSamw if ((xoap = xva_getxoptattr(xvap)) == NULL) { 91da6c28aaSamw xvap->xva_vattr.va_mask &= ~AT_XVATTR; /* shouldn't happen */ 92da6c28aaSamw return; 93da6c28aaSamw } 94da6c28aaSamw 95da6c28aaSamw ASSERT(lrattr->lr_attr_masksize == xvap->xva_mapsize); 96*569e6c63Smarks 97*569e6c63Smarks bitmap = &lrattr->lr_attr_bitmap; 98*569e6c63Smarks for (i = 0; i != lrattr->lr_attr_masksize; i++, bitmap++) 99*569e6c63Smarks xvap->xva_reqattrmap[i] = *bitmap; 100*569e6c63Smarks 101da6c28aaSamw attrs = (uint64_t *)(lrattr + lrattr->lr_attr_masksize - 1); 102da6c28aaSamw crtime = attrs + 1; 103da6c28aaSamw scanstamp = (caddr_t)(crtime + 2); 104da6c28aaSamw 105da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) 106da6c28aaSamw xoap->xoa_hidden = ((*attrs & XAT0_HIDDEN) != 0); 107da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) 108da6c28aaSamw xoap->xoa_system = ((*attrs & XAT0_SYSTEM) != 0); 109da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) 110da6c28aaSamw xoap->xoa_archive = ((*attrs & XAT0_ARCHIVE) != 0); 111da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_READONLY)) 112da6c28aaSamw xoap->xoa_readonly = ((*attrs & XAT0_READONLY) != 0); 113da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) 114da6c28aaSamw xoap->xoa_immutable = ((*attrs & XAT0_IMMUTABLE) != 0); 115da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) 116da6c28aaSamw xoap->xoa_nounlink = ((*attrs & XAT0_NOUNLINK) != 0); 117da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) 118da6c28aaSamw xoap->xoa_appendonly = ((*attrs & XAT0_APPENDONLY) != 0); 119da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) 120da6c28aaSamw xoap->xoa_nodump = ((*attrs & XAT0_NODUMP) != 0); 121da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) 122da6c28aaSamw xoap->xoa_opaque = ((*attrs & XAT0_OPAQUE) != 0); 123da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) 124da6c28aaSamw xoap->xoa_av_modified = ((*attrs & XAT0_AV_MODIFIED) != 0); 125da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) 126da6c28aaSamw xoap->xoa_av_quarantined = 127da6c28aaSamw ((*attrs & XAT0_AV_QUARANTINED) != 0); 128da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) 129da6c28aaSamw ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime); 130da6c28aaSamw if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) 131da6c28aaSamw bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); 132da6c28aaSamw } 133da6c28aaSamw 134da6c28aaSamw static int 135da6c28aaSamw zfs_replay_domain_cnt(uint64_t uid, uint64_t gid) 136da6c28aaSamw { 137da6c28aaSamw uint64_t uid_idx; 138da6c28aaSamw uint64_t gid_idx; 139da6c28aaSamw int domcnt = 0; 140da6c28aaSamw 141da6c28aaSamw uid_idx = FUID_INDEX(uid); 142da6c28aaSamw gid_idx = FUID_INDEX(gid); 143da6c28aaSamw if (uid_idx) 144da6c28aaSamw domcnt++; 145da6c28aaSamw if (gid_idx > 0 && gid_idx != uid_idx) 146da6c28aaSamw domcnt++; 147da6c28aaSamw 148da6c28aaSamw return (domcnt); 149da6c28aaSamw } 150da6c28aaSamw 151da6c28aaSamw static void * 152da6c28aaSamw zfs_replay_fuid_domain_common(zfs_fuid_info_t *fuid_infop, void *start, 153da6c28aaSamw int domcnt) 154da6c28aaSamw { 155da6c28aaSamw int i; 156da6c28aaSamw 157da6c28aaSamw for (i = 0; i != domcnt; i++) { 158da6c28aaSamw fuid_infop->z_domain_table[i] = start; 159da6c28aaSamw start = (caddr_t)start + strlen(start) + 1; 160da6c28aaSamw } 161da6c28aaSamw 162da6c28aaSamw return (start); 163da6c28aaSamw } 164da6c28aaSamw 165da6c28aaSamw /* 166da6c28aaSamw * Set the uid/gid in the fuid_info structure. 167da6c28aaSamw */ 168da6c28aaSamw static void 169da6c28aaSamw zfs_replay_fuid_ugid(zfs_fuid_info_t *fuid_infop, uint64_t uid, uint64_t gid) 170da6c28aaSamw { 171da6c28aaSamw /* 172da6c28aaSamw * If owner or group are log specific FUIDs then slurp up 173da6c28aaSamw * domain information and build zfs_fuid_info_t 174da6c28aaSamw */ 175da6c28aaSamw if (IS_EPHEMERAL(uid)) 176da6c28aaSamw fuid_infop->z_fuid_owner = uid; 177da6c28aaSamw 178da6c28aaSamw if (IS_EPHEMERAL(gid)) 179da6c28aaSamw fuid_infop->z_fuid_group = gid; 180da6c28aaSamw } 181da6c28aaSamw 182da6c28aaSamw /* 183da6c28aaSamw * Load fuid domains into fuid_info_t 184da6c28aaSamw */ 185da6c28aaSamw static zfs_fuid_info_t * 186da6c28aaSamw zfs_replay_fuid_domain(void *buf, void **end, uint64_t uid, uint64_t gid) 187da6c28aaSamw { 188da6c28aaSamw int domcnt; 189da6c28aaSamw 190da6c28aaSamw zfs_fuid_info_t *fuid_infop; 191da6c28aaSamw 192da6c28aaSamw fuid_infop = zfs_fuid_info_alloc(); 193da6c28aaSamw 194da6c28aaSamw domcnt = zfs_replay_domain_cnt(uid, gid); 195da6c28aaSamw 196da6c28aaSamw if (domcnt == 0) 197da6c28aaSamw return (fuid_infop); 198da6c28aaSamw 199da6c28aaSamw fuid_infop->z_domain_table = 200da6c28aaSamw kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 201da6c28aaSamw 202da6c28aaSamw zfs_replay_fuid_ugid(fuid_infop, uid, gid); 203da6c28aaSamw 204da6c28aaSamw fuid_infop->z_domain_cnt = domcnt; 205da6c28aaSamw *end = zfs_replay_fuid_domain_common(fuid_infop, buf, domcnt); 206da6c28aaSamw return (fuid_infop); 207da6c28aaSamw } 208da6c28aaSamw 209da6c28aaSamw /* 210da6c28aaSamw * load zfs_fuid_t's and fuid_domains into fuid_info_t 211da6c28aaSamw */ 212da6c28aaSamw static zfs_fuid_info_t * 213da6c28aaSamw zfs_replay_fuids(void *start, void **end, int idcnt, int domcnt, uint64_t uid, 214da6c28aaSamw uint64_t gid) 215da6c28aaSamw { 216da6c28aaSamw uint64_t *log_fuid = (uint64_t *)start; 217da6c28aaSamw zfs_fuid_info_t *fuid_infop; 218da6c28aaSamw int i; 219da6c28aaSamw 220da6c28aaSamw fuid_infop = zfs_fuid_info_alloc(); 221da6c28aaSamw fuid_infop->z_domain_cnt = domcnt; 222da6c28aaSamw 223da6c28aaSamw fuid_infop->z_domain_table = 224da6c28aaSamw kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 225da6c28aaSamw 226da6c28aaSamw for (i = 0; i != idcnt; i++) { 227da6c28aaSamw zfs_fuid_t *zfuid; 228da6c28aaSamw 229da6c28aaSamw zfuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP); 230da6c28aaSamw zfuid->z_logfuid = *log_fuid; 231da6c28aaSamw zfuid->z_id = -1; 232da6c28aaSamw zfuid->z_domidx = 0; 233da6c28aaSamw list_insert_tail(&fuid_infop->z_fuids, zfuid); 234da6c28aaSamw log_fuid++; 235da6c28aaSamw } 236da6c28aaSamw 237da6c28aaSamw zfs_replay_fuid_ugid(fuid_infop, uid, gid); 238da6c28aaSamw 239da6c28aaSamw *end = zfs_replay_fuid_domain_common(fuid_infop, log_fuid, domcnt); 240da6c28aaSamw return (fuid_infop); 241da6c28aaSamw } 242da6c28aaSamw 243da6c28aaSamw static void 244da6c28aaSamw zfs_replay_swap_attrs(lr_attr_t *lrattr) 245da6c28aaSamw { 246da6c28aaSamw /* swap the lr_attr structure */ 247da6c28aaSamw byteswap_uint32_array(lrattr, sizeof (*lrattr)); 248da6c28aaSamw /* swap the bitmap */ 249*569e6c63Smarks byteswap_uint32_array(lrattr + 1, (lrattr->lr_attr_masksize - 1) * 250*569e6c63Smarks sizeof (uint32_t)); 251da6c28aaSamw /* swap the attributes, create time + 64 bit word for attributes */ 252*569e6c63Smarks byteswap_uint64_array((caddr_t)(lrattr + 1) + (sizeof (uint32_t) * 253da6c28aaSamw (lrattr->lr_attr_masksize - 1)), 3 * sizeof (uint64_t)); 254da6c28aaSamw } 255da6c28aaSamw 256da6c28aaSamw /* 257da6c28aaSamw * Replay file create with optional ACL, xvattr information as well 258da6c28aaSamw * as option FUID information. 259da6c28aaSamw */ 260da6c28aaSamw static int 261da6c28aaSamw zfs_replay_create_acl(zfsvfs_t *zfsvfs, 262da6c28aaSamw lr_acl_create_t *lracl, boolean_t byteswap) 263da6c28aaSamw { 264da6c28aaSamw char *name = NULL; /* location determined later */ 265da6c28aaSamw lr_create_t *lr = (lr_create_t *)lracl; 266da6c28aaSamw znode_t *dzp; 267da6c28aaSamw vnode_t *vp = NULL; 268da6c28aaSamw xvattr_t xva; 269da6c28aaSamw int vflg = 0; 270da6c28aaSamw vsecattr_t vsec = { 0 }; 271da6c28aaSamw lr_attr_t *lrattr; 272da6c28aaSamw void *aclstart; 273da6c28aaSamw void *fuidstart; 274da6c28aaSamw size_t xvatlen = 0; 275da6c28aaSamw uint64_t txtype; 276da6c28aaSamw int error; 277da6c28aaSamw 278da6c28aaSamw if (byteswap) { 279da6c28aaSamw byteswap_uint64_array(lracl, sizeof (*lracl)); 280da6c28aaSamw txtype = (int)lr->lr_common.lrc_txtype; 281da6c28aaSamw if (txtype == TX_CREATE_ACL_ATTR || 282da6c28aaSamw txtype == TX_MKDIR_ACL_ATTR) { 283*569e6c63Smarks lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 284da6c28aaSamw zfs_replay_swap_attrs(lrattr); 285da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 286da6c28aaSamw } 287da6c28aaSamw 288da6c28aaSamw aclstart = (caddr_t)(lracl + 1) + xvatlen; 289da6c28aaSamw zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); 290da6c28aaSamw /* swap fuids */ 291da6c28aaSamw if (lracl->lr_fuidcnt) { 292da6c28aaSamw byteswap_uint64_array((caddr_t)aclstart + 293*569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes), 294*569e6c63Smarks lracl->lr_fuidcnt * sizeof (uint64_t)); 295da6c28aaSamw } 296da6c28aaSamw } 297da6c28aaSamw 298da6c28aaSamw if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 299da6c28aaSamw return (error); 300da6c28aaSamw 301da6c28aaSamw xva_init(&xva); 302da6c28aaSamw zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 303da6c28aaSamw lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 304da6c28aaSamw 305da6c28aaSamw /* 306da6c28aaSamw * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 307da6c28aaSamw * eventually end up in zfs_mknode(), which assigns the object's 308da6c28aaSamw * creation time and generation number. The generic VOP_CREATE() 309da6c28aaSamw * doesn't have either concept, so we smuggle the values inside 310da6c28aaSamw * the vattr's otherwise unused va_ctime and va_nblocks fields. 311da6c28aaSamw */ 312da6c28aaSamw ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 313da6c28aaSamw xva.xva_vattr.va_nblocks = lr->lr_gen; 314da6c28aaSamw 315da6c28aaSamw error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 316da6c28aaSamw if (error != ENOENT) 317da6c28aaSamw goto bail; 318da6c28aaSamw 319da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 320da6c28aaSamw vflg |= FIGNORECASE; 321da6c28aaSamw switch ((int)lr->lr_common.lrc_txtype) { 322da6c28aaSamw case TX_CREATE_ACL: 323da6c28aaSamw aclstart = (caddr_t)(lracl + 1); 324*569e6c63Smarks fuidstart = (caddr_t)aclstart + 325*569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 326da6c28aaSamw zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 327da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 328da6c28aaSamw lr->lr_uid, lr->lr_gid); 329da6c28aaSamw /*FALLTHROUGH*/ 330da6c28aaSamw case TX_CREATE_ACL_ATTR: 331da6c28aaSamw if (name == NULL) { 332da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 333da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 334da6c28aaSamw xva.xva_vattr.va_mask |= AT_XVATTR; 335da6c28aaSamw zfs_replay_xvattr(lrattr, &xva); 336da6c28aaSamw } 337da6c28aaSamw vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 338da6c28aaSamw vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 339da6c28aaSamw vsec.vsa_aclcnt = lracl->lr_aclcnt; 340da6c28aaSamw vsec.vsa_aclentsz = lracl->lr_acl_bytes; 341da6c28aaSamw vsec.vsa_aclflags = lracl->lr_acl_flags; 342da6c28aaSamw if (zfsvfs->z_fuid_replay == NULL) 343da6c28aaSamw fuidstart = (caddr_t)(lracl + 1) + xvatlen + 344*569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 345da6c28aaSamw zfsvfs->z_fuid_replay = 346da6c28aaSamw zfs_replay_fuids(fuidstart, 347da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 348da6c28aaSamw lr->lr_uid, lr->lr_gid); 349da6c28aaSamw 350da6c28aaSamw error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 351da6c28aaSamw 0, 0, &vp, kcred, vflg, NULL, &vsec); 352da6c28aaSamw break; 353da6c28aaSamw case TX_MKDIR_ACL: 354da6c28aaSamw aclstart = (caddr_t)(lracl + 1); 355*569e6c63Smarks fuidstart = (caddr_t)aclstart + 356*569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 357da6c28aaSamw zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 358da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 359da6c28aaSamw lr->lr_uid, lr->lr_gid); 360da6c28aaSamw /*FALLTHROUGH*/ 361da6c28aaSamw case TX_MKDIR_ACL_ATTR: 362da6c28aaSamw if (name == NULL) { 363da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 364da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 365da6c28aaSamw zfs_replay_xvattr(lrattr, &xva); 366da6c28aaSamw } 367da6c28aaSamw vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 368da6c28aaSamw vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 369da6c28aaSamw vsec.vsa_aclcnt = lracl->lr_aclcnt; 370da6c28aaSamw vsec.vsa_aclentsz = lracl->lr_acl_bytes; 371da6c28aaSamw vsec.vsa_aclflags = lracl->lr_acl_flags; 372da6c28aaSamw if (zfsvfs->z_fuid_replay == NULL) 373da6c28aaSamw fuidstart = (caddr_t)(lracl + 1) + xvatlen + 374*569e6c63Smarks ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 375da6c28aaSamw zfsvfs->z_fuid_replay = 376da6c28aaSamw zfs_replay_fuids(fuidstart, 377da6c28aaSamw (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 378da6c28aaSamw lr->lr_uid, lr->lr_gid); 379da6c28aaSamw error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, 380da6c28aaSamw &vp, kcred, NULL, vflg, &vsec); 381da6c28aaSamw break; 382da6c28aaSamw default: 383da6c28aaSamw error = ENOTSUP; 384da6c28aaSamw } 385da6c28aaSamw 386da6c28aaSamw bail: 387da6c28aaSamw if (error == 0 && vp != NULL) 388da6c28aaSamw VN_RELE(vp); 389da6c28aaSamw 390da6c28aaSamw VN_RELE(ZTOV(dzp)); 391da6c28aaSamw 392da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 393da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 394da6c28aaSamw 395da6c28aaSamw return (error); 396da6c28aaSamw } 397da6c28aaSamw 398fa9e4066Sahrens static int 399fa9e4066Sahrens zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) 400fa9e4066Sahrens { 401da6c28aaSamw char *name = NULL; /* location determined later */ 402fa9e4066Sahrens char *link; /* symlink content follows name */ 403fa9e4066Sahrens znode_t *dzp; 404fa9e4066Sahrens vnode_t *vp = NULL; 405da6c28aaSamw xvattr_t xva; 406da6c28aaSamw int vflg = 0; 407da6c28aaSamw size_t lrsize = sizeof (lr_create_t); 408da6c28aaSamw lr_attr_t *lrattr; 409da6c28aaSamw void *start; 410da6c28aaSamw size_t xvatlen; 411da6c28aaSamw uint64_t txtype; 412fa9e4066Sahrens int error; 413fa9e4066Sahrens 414da6c28aaSamw if (byteswap) { 415fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 416da6c28aaSamw txtype = (int)lr->lr_common.lrc_txtype; 417da6c28aaSamw if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) 418da6c28aaSamw zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 419da6c28aaSamw } 420da6c28aaSamw 421fa9e4066Sahrens 422fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 423fa9e4066Sahrens return (error); 424fa9e4066Sahrens 425da6c28aaSamw xva_init(&xva); 426da6c28aaSamw zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 427fa9e4066Sahrens lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 428fa9e4066Sahrens 429fa9e4066Sahrens /* 430fa9e4066Sahrens * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 431fa9e4066Sahrens * eventually end up in zfs_mknode(), which assigns the object's 432fa9e4066Sahrens * creation time and generation number. The generic VOP_CREATE() 433fa9e4066Sahrens * doesn't have either concept, so we smuggle the values inside 434fa9e4066Sahrens * the vattr's otherwise unused va_ctime and va_nblocks fields. 435fa9e4066Sahrens */ 436da6c28aaSamw ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 437da6c28aaSamw xva.xva_vattr.va_nblocks = lr->lr_gen; 438fa9e4066Sahrens 439758f6e0bSgw error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 440758f6e0bSgw if (error != ENOENT) 441758f6e0bSgw goto out; 442758f6e0bSgw 443da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 444da6c28aaSamw vflg |= FIGNORECASE; 445da6c28aaSamw 446da6c28aaSamw /* 447da6c28aaSamw * Symlinks don't have fuid info, and CIFS never creates 448da6c28aaSamw * symlinks. 449da6c28aaSamw * 450da6c28aaSamw * The _ATTR versions will grab the fuid info in their subcases. 451da6c28aaSamw */ 452da6c28aaSamw if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK && 453da6c28aaSamw (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR && 454da6c28aaSamw (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) { 455da6c28aaSamw start = (lr + 1); 456da6c28aaSamw zfsvfs->z_fuid_replay = 457da6c28aaSamw zfs_replay_fuid_domain(start, &start, 458da6c28aaSamw lr->lr_uid, lr->lr_gid); 459da6c28aaSamw } 460da6c28aaSamw 461fa9e4066Sahrens switch ((int)lr->lr_common.lrc_txtype) { 462da6c28aaSamw case TX_CREATE_ATTR: 463da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 464da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 465da6c28aaSamw zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 466da6c28aaSamw start = (caddr_t)(lr + 1) + xvatlen; 467da6c28aaSamw zfsvfs->z_fuid_replay = 468da6c28aaSamw zfs_replay_fuid_domain(start, &start, 469da6c28aaSamw lr->lr_uid, lr->lr_gid); 470da6c28aaSamw name = (char *)start; 471da6c28aaSamw 472da6c28aaSamw /*FALLTHROUGH*/ 473fa9e4066Sahrens case TX_CREATE: 474da6c28aaSamw if (name == NULL) 475da6c28aaSamw name = (char *)start; 476da6c28aaSamw 477da6c28aaSamw error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 478da6c28aaSamw 0, 0, &vp, kcred, vflg, NULL, NULL); 479fa9e4066Sahrens break; 480da6c28aaSamw case TX_MKDIR_ATTR: 481da6c28aaSamw lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 482da6c28aaSamw xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 483da6c28aaSamw zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 484da6c28aaSamw start = (caddr_t)(lr + 1) + xvatlen; 485da6c28aaSamw zfsvfs->z_fuid_replay = 486da6c28aaSamw zfs_replay_fuid_domain(start, &start, 487da6c28aaSamw lr->lr_uid, lr->lr_gid); 488da6c28aaSamw name = (char *)start; 489da6c28aaSamw 490da6c28aaSamw /*FALLTHROUGH*/ 491fa9e4066Sahrens case TX_MKDIR: 492da6c28aaSamw if (name == NULL) 493da6c28aaSamw name = (char *)(lr + 1); 494da6c28aaSamw 495da6c28aaSamw error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, 496da6c28aaSamw &vp, kcred, NULL, vflg, NULL); 497fa9e4066Sahrens break; 498fa9e4066Sahrens case TX_MKXATTR: 499da6c28aaSamw name = (char *)(lr + 1); 500da6c28aaSamw error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &vp, kcred); 501fa9e4066Sahrens break; 502fa9e4066Sahrens case TX_SYMLINK: 503da6c28aaSamw name = (char *)(lr + 1); 504fa9e4066Sahrens link = name + strlen(name) + 1; 505da6c28aaSamw error = VOP_SYMLINK(ZTOV(dzp), name, &xva.xva_vattr, 506da6c28aaSamw link, kcred, NULL, vflg); 507fa9e4066Sahrens break; 508fa9e4066Sahrens default: 509fa9e4066Sahrens error = ENOTSUP; 510fa9e4066Sahrens } 511fa9e4066Sahrens 512758f6e0bSgw out: 513fa9e4066Sahrens if (error == 0 && vp != NULL) 514fa9e4066Sahrens VN_RELE(vp); 515fa9e4066Sahrens 516fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 517fa9e4066Sahrens 518da6c28aaSamw if (zfsvfs->z_fuid_replay) 519da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 520da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 521fa9e4066Sahrens return (error); 522fa9e4066Sahrens } 523fa9e4066Sahrens 524fa9e4066Sahrens static int 525fa9e4066Sahrens zfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap) 526fa9e4066Sahrens { 527fa9e4066Sahrens char *name = (char *)(lr + 1); /* name follows lr_remove_t */ 528fa9e4066Sahrens znode_t *dzp; 529fa9e4066Sahrens int error; 530da6c28aaSamw int vflg = 0; 531fa9e4066Sahrens 532fa9e4066Sahrens if (byteswap) 533fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 534fa9e4066Sahrens 535fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 536fa9e4066Sahrens return (error); 537fa9e4066Sahrens 538da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 539da6c28aaSamw vflg |= FIGNORECASE; 540da6c28aaSamw 541fa9e4066Sahrens switch ((int)lr->lr_common.lrc_txtype) { 542fa9e4066Sahrens case TX_REMOVE: 543da6c28aaSamw error = VOP_REMOVE(ZTOV(dzp), name, kcred, NULL, vflg); 544fa9e4066Sahrens break; 545fa9e4066Sahrens case TX_RMDIR: 546da6c28aaSamw error = VOP_RMDIR(ZTOV(dzp), name, NULL, kcred, NULL, vflg); 547fa9e4066Sahrens break; 548fa9e4066Sahrens default: 549fa9e4066Sahrens error = ENOTSUP; 550fa9e4066Sahrens } 551fa9e4066Sahrens 552fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 553fa9e4066Sahrens 554fa9e4066Sahrens return (error); 555fa9e4066Sahrens } 556fa9e4066Sahrens 557fa9e4066Sahrens static int 558fa9e4066Sahrens zfs_replay_link(zfsvfs_t *zfsvfs, lr_link_t *lr, boolean_t byteswap) 559fa9e4066Sahrens { 560fa9e4066Sahrens char *name = (char *)(lr + 1); /* name follows lr_link_t */ 561fa9e4066Sahrens znode_t *dzp, *zp; 562fa9e4066Sahrens int error; 563da6c28aaSamw int vflg = 0; 564fa9e4066Sahrens 565fa9e4066Sahrens if (byteswap) 566fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 567fa9e4066Sahrens 568fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 569fa9e4066Sahrens return (error); 570fa9e4066Sahrens 571fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_link_obj, &zp)) != 0) { 572fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 573fa9e4066Sahrens return (error); 574fa9e4066Sahrens } 575fa9e4066Sahrens 576da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 577da6c28aaSamw vflg |= FIGNORECASE; 578da6c28aaSamw 579da6c28aaSamw error = VOP_LINK(ZTOV(dzp), ZTOV(zp), name, kcred, NULL, vflg); 580fa9e4066Sahrens 581fa9e4066Sahrens VN_RELE(ZTOV(zp)); 582fa9e4066Sahrens VN_RELE(ZTOV(dzp)); 583fa9e4066Sahrens 584fa9e4066Sahrens return (error); 585fa9e4066Sahrens } 586fa9e4066Sahrens 587fa9e4066Sahrens static int 588fa9e4066Sahrens zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap) 589fa9e4066Sahrens { 590fa9e4066Sahrens char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ 591fa9e4066Sahrens char *tname = sname + strlen(sname) + 1; 592fa9e4066Sahrens znode_t *sdzp, *tdzp; 593fa9e4066Sahrens int error; 594da6c28aaSamw int vflg = 0; 595fa9e4066Sahrens 596fa9e4066Sahrens if (byteswap) 597fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 598fa9e4066Sahrens 599fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) 600fa9e4066Sahrens return (error); 601fa9e4066Sahrens 602fa9e4066Sahrens if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { 603fa9e4066Sahrens VN_RELE(ZTOV(sdzp)); 604fa9e4066Sahrens return (error); 605fa9e4066Sahrens } 606fa9e4066Sahrens 607da6c28aaSamw if (lr->lr_common.lrc_txtype & TX_CI) 608da6c28aaSamw vflg |= FIGNORECASE; 609da6c28aaSamw 610da6c28aaSamw error = VOP_RENAME(ZTOV(sdzp), sname, ZTOV(tdzp), tname, kcred, 611da6c28aaSamw NULL, vflg); 612fa9e4066Sahrens 613fa9e4066Sahrens VN_RELE(ZTOV(tdzp)); 614fa9e4066Sahrens VN_RELE(ZTOV(sdzp)); 615fa9e4066Sahrens 616fa9e4066Sahrens return (error); 617fa9e4066Sahrens } 618fa9e4066Sahrens 619fa9e4066Sahrens static int 620fa9e4066Sahrens zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 621fa9e4066Sahrens { 622fa9e4066Sahrens char *data = (char *)(lr + 1); /* data follows lr_write_t */ 623fa9e4066Sahrens znode_t *zp; 624fa9e4066Sahrens int error; 625fa9e4066Sahrens ssize_t resid; 626fa9e4066Sahrens 627fa9e4066Sahrens if (byteswap) 628fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 629fa9e4066Sahrens 630b19a79ecSperrin if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 631b19a79ecSperrin /* 632b19a79ecSperrin * As we can log writes out of order, it's possible the 633b19a79ecSperrin * file has been removed. In this case just drop the write 634b19a79ecSperrin * and return success. 635b19a79ecSperrin */ 636b19a79ecSperrin if (error == ENOENT) 637b19a79ecSperrin error = 0; 638fa9e4066Sahrens return (error); 639b19a79ecSperrin } 640fa9e4066Sahrens 641fa9e4066Sahrens error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, lr->lr_length, 642fa9e4066Sahrens lr->lr_offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); 643fa9e4066Sahrens 644fa9e4066Sahrens VN_RELE(ZTOV(zp)); 645fa9e4066Sahrens 646fa9e4066Sahrens return (error); 647fa9e4066Sahrens } 648fa9e4066Sahrens 649fa9e4066Sahrens static int 650fa9e4066Sahrens zfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap) 651fa9e4066Sahrens { 652fa9e4066Sahrens znode_t *zp; 653fa9e4066Sahrens flock64_t fl; 654fa9e4066Sahrens int error; 655fa9e4066Sahrens 656fa9e4066Sahrens if (byteswap) 657fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 658fa9e4066Sahrens 659b19a79ecSperrin if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 660b19a79ecSperrin /* 661b19a79ecSperrin * As we can log truncates out of order, it's possible the 662b19a79ecSperrin * file has been removed. In this case just drop the truncate 663b19a79ecSperrin * and return success. 664b19a79ecSperrin */ 665b19a79ecSperrin if (error == ENOENT) 666b19a79ecSperrin error = 0; 667fa9e4066Sahrens return (error); 668b19a79ecSperrin } 669fa9e4066Sahrens 670fa9e4066Sahrens bzero(&fl, sizeof (fl)); 671fa9e4066Sahrens fl.l_type = F_WRLCK; 672fa9e4066Sahrens fl.l_whence = 0; 673fa9e4066Sahrens fl.l_start = lr->lr_offset; 674fa9e4066Sahrens fl.l_len = lr->lr_length; 675fa9e4066Sahrens 676fa9e4066Sahrens error = VOP_SPACE(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX, 677fa9e4066Sahrens lr->lr_offset, kcred, NULL); 678fa9e4066Sahrens 679fa9e4066Sahrens VN_RELE(ZTOV(zp)); 680fa9e4066Sahrens 681fa9e4066Sahrens return (error); 682fa9e4066Sahrens } 683fa9e4066Sahrens 684fa9e4066Sahrens static int 685fa9e4066Sahrens zfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap) 686fa9e4066Sahrens { 687fa9e4066Sahrens znode_t *zp; 688da6c28aaSamw xvattr_t xva; 689da6c28aaSamw vattr_t *vap = &xva.xva_vattr; 690fa9e4066Sahrens int error; 691da6c28aaSamw void *start; 692fa9e4066Sahrens 693da6c28aaSamw xva_init(&xva); 694da6c28aaSamw if (byteswap) { 695fa9e4066Sahrens byteswap_uint64_array(lr, sizeof (*lr)); 696fa9e4066Sahrens 697da6c28aaSamw if ((lr->lr_mask & AT_XVATTR) && 698da6c28aaSamw zfsvfs->z_version >= ZPL_VERSION_INITIAL) 699da6c28aaSamw zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 700da6c28aaSamw } 701da6c28aaSamw 702b19a79ecSperrin if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 703b19a79ecSperrin /* 704b19a79ecSperrin * As we can log setattrs out of order, it's possible the 705b19a79ecSperrin * file has been removed. In this case just drop the setattr 706b19a79ecSperrin * and return success. 707b19a79ecSperrin */ 708b19a79ecSperrin if (error == ENOENT) 709b19a79ecSperrin error = 0; 710fa9e4066Sahrens return (error); 711b19a79ecSperrin } 712fa9e4066Sahrens 713da6c28aaSamw zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, 714fa9e4066Sahrens lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); 715fa9e4066Sahrens 716da6c28aaSamw vap->va_size = lr->lr_size; 717da6c28aaSamw ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); 718da6c28aaSamw ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); 719da6c28aaSamw 720da6c28aaSamw /* 721da6c28aaSamw * Fill in xvattr_t portions if necessary. 722da6c28aaSamw */ 723da6c28aaSamw 724da6c28aaSamw start = (lr_setattr_t *)(lr + 1); 725da6c28aaSamw if (vap->va_mask & AT_XVATTR) { 726da6c28aaSamw zfs_replay_xvattr((lr_attr_t *)start, &xva); 727da6c28aaSamw start = (caddr_t)start + 728da6c28aaSamw ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); 729da6c28aaSamw } else 730da6c28aaSamw xva.xva_vattr.va_mask &= ~AT_XVATTR; 731da6c28aaSamw 732da6c28aaSamw zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, 733da6c28aaSamw lr->lr_uid, lr->lr_gid); 734fa9e4066Sahrens 735da6c28aaSamw error = VOP_SETATTR(ZTOV(zp), vap, 0, kcred, NULL); 736fa9e4066Sahrens 737da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 738da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 739fa9e4066Sahrens VN_RELE(ZTOV(zp)); 740fa9e4066Sahrens 741fa9e4066Sahrens return (error); 742fa9e4066Sahrens } 743fa9e4066Sahrens 744fa9e4066Sahrens static int 745da6c28aaSamw zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap) 746fa9e4066Sahrens { 747fa9e4066Sahrens ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */ 748fa9e4066Sahrens vsecattr_t vsa; 749fa9e4066Sahrens znode_t *zp; 750fa9e4066Sahrens int error; 751fa9e4066Sahrens 752*569e6c63Smarks if (byteswap) { 753*569e6c63Smarks byteswap_uint64_array(lr, sizeof (*lr)); 754*569e6c63Smarks zfs_oldace_byteswap(ace, lr->lr_aclcnt); 755*569e6c63Smarks } 756*569e6c63Smarks 757da6c28aaSamw if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 758da6c28aaSamw /* 759da6c28aaSamw * As we can log acls out of order, it's possible the 760da6c28aaSamw * file has been removed. In this case just drop the acl 761da6c28aaSamw * and return success. 762da6c28aaSamw */ 763da6c28aaSamw if (error == ENOENT) 764da6c28aaSamw error = 0; 765da6c28aaSamw return (error); 766da6c28aaSamw } 767da6c28aaSamw 768da6c28aaSamw bzero(&vsa, sizeof (vsa)); 769da6c28aaSamw vsa.vsa_mask = VSA_ACE | VSA_ACECNT; 770da6c28aaSamw vsa.vsa_aclcnt = lr->lr_aclcnt; 771da6c28aaSamw vsa.vsa_aclentp = ace; 772da6c28aaSamw 773da6c28aaSamw error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); 774da6c28aaSamw 775da6c28aaSamw VN_RELE(ZTOV(zp)); 776da6c28aaSamw 777da6c28aaSamw return (error); 778da6c28aaSamw } 779da6c28aaSamw 780da6c28aaSamw /* 781da6c28aaSamw * Replaying ACLs is complicated by FUID support. 782da6c28aaSamw * The log record may contain some optional data 783da6c28aaSamw * to be used for replaying FUID's. These pieces 784da6c28aaSamw * are the actual FUIDs that were created initially. 785da6c28aaSamw * The FUID table index may no longer be valid and 786da6c28aaSamw * during zfs_create() a new index may be assigned. 787da6c28aaSamw * Because of this the log will contain the original 788da6c28aaSamw * doman+rid in order to create a new FUID. 789da6c28aaSamw * 790da6c28aaSamw * The individual ACEs may contain an ephemeral uid/gid which is no 791da6c28aaSamw * longer valid and will need to be replaced with an actual FUID. 792da6c28aaSamw * 793da6c28aaSamw */ 794da6c28aaSamw static int 795da6c28aaSamw zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap) 796da6c28aaSamw { 797da6c28aaSamw ace_t *ace = (ace_t *)(lr + 1); 798da6c28aaSamw vsecattr_t vsa; 799da6c28aaSamw znode_t *zp; 800da6c28aaSamw int error; 801da6c28aaSamw 802*569e6c63Smarks if (byteswap) { 803*569e6c63Smarks byteswap_uint64_array(lr, sizeof (*lr)); 804*569e6c63Smarks zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE); 805*569e6c63Smarks if (lr->lr_fuidcnt) { 806*569e6c63Smarks byteswap_uint64_array((caddr_t)ace + 807*569e6c63Smarks ZIL_ACE_LENGTH(lr->lr_acl_bytes), 808*569e6c63Smarks lr->lr_fuidcnt * sizeof (uint64_t)); 809*569e6c63Smarks } 810*569e6c63Smarks } 811*569e6c63Smarks 812b19a79ecSperrin if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 813b19a79ecSperrin /* 814b19a79ecSperrin * As we can log acls out of order, it's possible the 815b19a79ecSperrin * file has been removed. In this case just drop the acl 816b19a79ecSperrin * and return success. 817b19a79ecSperrin */ 818b19a79ecSperrin if (error == ENOENT) 819b19a79ecSperrin error = 0; 820fa9e4066Sahrens return (error); 821b19a79ecSperrin } 822fa9e4066Sahrens 823fa9e4066Sahrens bzero(&vsa, sizeof (vsa)); 824da6c28aaSamw vsa.vsa_mask = VSA_ACE | VSA_ACECNT | VSA_ACE_ACLFLAGS; 825fa9e4066Sahrens vsa.vsa_aclcnt = lr->lr_aclcnt; 826fa9e4066Sahrens vsa.vsa_aclentp = ace; 827da6c28aaSamw vsa.vsa_aclentsz = lr->lr_acl_bytes; 828da6c28aaSamw vsa.vsa_aclflags = lr->lr_acl_flags; 829da6c28aaSamw 830da6c28aaSamw if (lr->lr_fuidcnt) { 831*569e6c63Smarks void *fuidstart = (caddr_t)ace + 832*569e6c63Smarks ZIL_ACE_LENGTH(lr->lr_acl_bytes); 833da6c28aaSamw 834da6c28aaSamw zfsvfs->z_fuid_replay = 835da6c28aaSamw zfs_replay_fuids(fuidstart, &fuidstart, 836da6c28aaSamw lr->lr_fuidcnt, lr->lr_domcnt, 0, 0); 837da6c28aaSamw } 838da6c28aaSamw 839da6c28aaSamw error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); 840fa9e4066Sahrens 841da6c28aaSamw if (zfsvfs->z_fuid_replay) 842da6c28aaSamw zfs_fuid_info_free(zfsvfs->z_fuid_replay); 843fa9e4066Sahrens 844da6c28aaSamw zfsvfs->z_fuid_replay = NULL; 845fa9e4066Sahrens VN_RELE(ZTOV(zp)); 846fa9e4066Sahrens 847fa9e4066Sahrens return (error); 848fa9e4066Sahrens } 849fa9e4066Sahrens 850fa9e4066Sahrens /* 851fa9e4066Sahrens * Callback vectors for replaying records 852fa9e4066Sahrens */ 853fa9e4066Sahrens zil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE] = { 854fa9e4066Sahrens zfs_replay_error, /* 0 no such transaction type */ 855fa9e4066Sahrens zfs_replay_create, /* TX_CREATE */ 856fa9e4066Sahrens zfs_replay_create, /* TX_MKDIR */ 857fa9e4066Sahrens zfs_replay_create, /* TX_MKXATTR */ 858fa9e4066Sahrens zfs_replay_create, /* TX_SYMLINK */ 859fa9e4066Sahrens zfs_replay_remove, /* TX_REMOVE */ 860fa9e4066Sahrens zfs_replay_remove, /* TX_RMDIR */ 861fa9e4066Sahrens zfs_replay_link, /* TX_LINK */ 862fa9e4066Sahrens zfs_replay_rename, /* TX_RENAME */ 863fa9e4066Sahrens zfs_replay_write, /* TX_WRITE */ 864fa9e4066Sahrens zfs_replay_truncate, /* TX_TRUNCATE */ 865fa9e4066Sahrens zfs_replay_setattr, /* TX_SETATTR */ 866da6c28aaSamw zfs_replay_acl_v0, /* TX_ACL_V0 */ 867fa9e4066Sahrens zfs_replay_acl, /* TX_ACL */ 868da6c28aaSamw zfs_replay_create_acl, /* TX_CREATE_ACL */ 869da6c28aaSamw zfs_replay_create, /* TX_CREATE_ATTR */ 870da6c28aaSamw zfs_replay_create_acl, /* TX_CREATE_ACL_ATTR */ 871da6c28aaSamw zfs_replay_create_acl, /* TX_MKDIR_ACL */ 872da6c28aaSamw zfs_replay_create, /* TX_MKDIR_ATTR */ 873da6c28aaSamw zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */ 874fa9e4066Sahrens }; 875