1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23249195Smm * Copyright (c) 2013 by Delphix. All rights reserved. 24168404Spjd */ 25168404Spjd 26168404Spjd#include <sys/types.h> 27168404Spjd#include <sys/param.h> 28168404Spjd#include <sys/systm.h> 29168404Spjd#include <sys/sysmacros.h> 30168404Spjd#include <sys/cmn_err.h> 31168404Spjd#include <sys/kmem.h> 32168404Spjd#include <sys/file.h> 33168404Spjd#include <sys/fcntl.h> 34168404Spjd#include <sys/vfs.h> 35168404Spjd#include <sys/fs/zfs.h> 36168404Spjd#include <sys/zfs_znode.h> 37168404Spjd#include <sys/zfs_dir.h> 38168404Spjd#include <sys/zfs_acl.h> 39185029Spjd#include <sys/zfs_fuid.h> 40168404Spjd#include <sys/spa.h> 41168404Spjd#include <sys/zil.h> 42168404Spjd#include <sys/byteorder.h> 43168404Spjd#include <sys/stat.h> 44168404Spjd#include <sys/acl.h> 45168404Spjd#include <sys/atomic.h> 46168404Spjd#include <sys/cred.h> 47168404Spjd#include <sys/namei.h> 48168404Spjd 49168404Spjd/* 50168404Spjd * Functions to replay ZFS intent log (ZIL) records 51168404Spjd * The functions are called through a function vector (zfs_replay_vector) 52168404Spjd * which is indexed by the transaction type. 53168404Spjd */ 54168404Spjd 55168404Spjdstatic void 56168404Spjdzfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode, 57168404Spjd uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid) 58168404Spjd{ 59168404Spjd VATTR_NULL(vap); 60168404Spjd vap->va_mask = (uint_t)mask; 61199157Spjd if (mask & AT_TYPE) 62199157Spjd vap->va_type = IFTOVT(mode); 63199157Spjd if (mask & AT_MODE) 64199157Spjd vap->va_mode = mode & MODEMASK; 65199157Spjd if (mask & AT_UID) 66199157Spjd vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; 67199157Spjd if (mask & AT_GID) 68199157Spjd vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; 69168404Spjd vap->va_rdev = zfs_cmpldev(rdev); 70168404Spjd vap->va_nodeid = nodeid; 71168404Spjd} 72168404Spjd 73168404Spjd/* ARGSUSED */ 74168404Spjdstatic int 75168404Spjdzfs_replay_error(zfsvfs_t *zfsvfs, lr_t *lr, boolean_t byteswap) 76168404Spjd{ 77249195Smm return (SET_ERROR(ENOTSUP)); 78168404Spjd} 79168404Spjd 80185029Spjdstatic void 81185029Spjdzfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 82185029Spjd{ 83185029Spjd xoptattr_t *xoap = NULL; 84185029Spjd uint64_t *attrs; 85185029Spjd uint64_t *crtime; 86185029Spjd uint32_t *bitmap; 87185029Spjd void *scanstamp; 88185029Spjd int i; 89185029Spjd 90185029Spjd xvap->xva_vattr.va_mask |= AT_XVATTR; 91185029Spjd if ((xoap = xva_getxoptattr(xvap)) == NULL) { 92185029Spjd xvap->xva_vattr.va_mask &= ~AT_XVATTR; /* shouldn't happen */ 93185029Spjd return; 94185029Spjd } 95185029Spjd 96185029Spjd ASSERT(lrattr->lr_attr_masksize == xvap->xva_mapsize); 97185029Spjd 98185029Spjd bitmap = &lrattr->lr_attr_bitmap; 99185029Spjd for (i = 0; i != lrattr->lr_attr_masksize; i++, bitmap++) 100185029Spjd xvap->xva_reqattrmap[i] = *bitmap; 101185029Spjd 102185029Spjd attrs = (uint64_t *)(lrattr + lrattr->lr_attr_masksize - 1); 103185029Spjd crtime = attrs + 1; 104185029Spjd scanstamp = (caddr_t)(crtime + 2); 105185029Spjd 106185029Spjd if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) 107185029Spjd xoap->xoa_hidden = ((*attrs & XAT0_HIDDEN) != 0); 108185029Spjd if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) 109185029Spjd xoap->xoa_system = ((*attrs & XAT0_SYSTEM) != 0); 110185029Spjd if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) 111185029Spjd xoap->xoa_archive = ((*attrs & XAT0_ARCHIVE) != 0); 112185029Spjd if (XVA_ISSET_REQ(xvap, XAT_READONLY)) 113185029Spjd xoap->xoa_readonly = ((*attrs & XAT0_READONLY) != 0); 114185029Spjd if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) 115185029Spjd xoap->xoa_immutable = ((*attrs & XAT0_IMMUTABLE) != 0); 116185029Spjd if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) 117185029Spjd xoap->xoa_nounlink = ((*attrs & XAT0_NOUNLINK) != 0); 118185029Spjd if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) 119185029Spjd xoap->xoa_appendonly = ((*attrs & XAT0_APPENDONLY) != 0); 120185029Spjd if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) 121185029Spjd xoap->xoa_nodump = ((*attrs & XAT0_NODUMP) != 0); 122185029Spjd if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) 123185029Spjd xoap->xoa_opaque = ((*attrs & XAT0_OPAQUE) != 0); 124185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) 125185029Spjd xoap->xoa_av_modified = ((*attrs & XAT0_AV_MODIFIED) != 0); 126185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) 127185029Spjd xoap->xoa_av_quarantined = 128185029Spjd ((*attrs & XAT0_AV_QUARANTINED) != 0); 129185029Spjd if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) 130185029Spjd ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime); 131185029Spjd if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) 132185029Spjd bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); 133219089Spjd if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) 134219089Spjd xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); 135219089Spjd if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) 136219089Spjd xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0); 137219089Spjd if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) 138219089Spjd xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); 139185029Spjd} 140185029Spjd 141168404Spjdstatic int 142185029Spjdzfs_replay_domain_cnt(uint64_t uid, uint64_t gid) 143185029Spjd{ 144185029Spjd uint64_t uid_idx; 145185029Spjd uint64_t gid_idx; 146185029Spjd int domcnt = 0; 147185029Spjd 148185029Spjd uid_idx = FUID_INDEX(uid); 149185029Spjd gid_idx = FUID_INDEX(gid); 150185029Spjd if (uid_idx) 151185029Spjd domcnt++; 152185029Spjd if (gid_idx > 0 && gid_idx != uid_idx) 153185029Spjd domcnt++; 154185029Spjd 155185029Spjd return (domcnt); 156185029Spjd} 157185029Spjd 158185029Spjdstatic void * 159185029Spjdzfs_replay_fuid_domain_common(zfs_fuid_info_t *fuid_infop, void *start, 160185029Spjd int domcnt) 161185029Spjd{ 162185029Spjd int i; 163185029Spjd 164185029Spjd for (i = 0; i != domcnt; i++) { 165185029Spjd fuid_infop->z_domain_table[i] = start; 166185029Spjd start = (caddr_t)start + strlen(start) + 1; 167185029Spjd } 168185029Spjd 169185029Spjd return (start); 170185029Spjd} 171185029Spjd 172185029Spjd/* 173185029Spjd * Set the uid/gid in the fuid_info structure. 174185029Spjd */ 175185029Spjdstatic void 176185029Spjdzfs_replay_fuid_ugid(zfs_fuid_info_t *fuid_infop, uint64_t uid, uint64_t gid) 177185029Spjd{ 178185029Spjd /* 179185029Spjd * If owner or group are log specific FUIDs then slurp up 180185029Spjd * domain information and build zfs_fuid_info_t 181185029Spjd */ 182185029Spjd if (IS_EPHEMERAL(uid)) 183185029Spjd fuid_infop->z_fuid_owner = uid; 184185029Spjd 185185029Spjd if (IS_EPHEMERAL(gid)) 186185029Spjd fuid_infop->z_fuid_group = gid; 187185029Spjd} 188185029Spjd 189185029Spjd/* 190185029Spjd * Load fuid domains into fuid_info_t 191185029Spjd */ 192185029Spjdstatic zfs_fuid_info_t * 193185029Spjdzfs_replay_fuid_domain(void *buf, void **end, uint64_t uid, uint64_t gid) 194185029Spjd{ 195185029Spjd int domcnt; 196185029Spjd 197185029Spjd zfs_fuid_info_t *fuid_infop; 198185029Spjd 199185029Spjd fuid_infop = zfs_fuid_info_alloc(); 200185029Spjd 201185029Spjd domcnt = zfs_replay_domain_cnt(uid, gid); 202185029Spjd 203185029Spjd if (domcnt == 0) 204185029Spjd return (fuid_infop); 205185029Spjd 206185029Spjd fuid_infop->z_domain_table = 207185029Spjd kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 208185029Spjd 209185029Spjd zfs_replay_fuid_ugid(fuid_infop, uid, gid); 210185029Spjd 211185029Spjd fuid_infop->z_domain_cnt = domcnt; 212185029Spjd *end = zfs_replay_fuid_domain_common(fuid_infop, buf, domcnt); 213185029Spjd return (fuid_infop); 214185029Spjd} 215185029Spjd 216185029Spjd/* 217185029Spjd * load zfs_fuid_t's and fuid_domains into fuid_info_t 218185029Spjd */ 219185029Spjdstatic zfs_fuid_info_t * 220185029Spjdzfs_replay_fuids(void *start, void **end, int idcnt, int domcnt, uint64_t uid, 221185029Spjd uint64_t gid) 222185029Spjd{ 223185029Spjd uint64_t *log_fuid = (uint64_t *)start; 224185029Spjd zfs_fuid_info_t *fuid_infop; 225185029Spjd int i; 226185029Spjd 227185029Spjd fuid_infop = zfs_fuid_info_alloc(); 228185029Spjd fuid_infop->z_domain_cnt = domcnt; 229185029Spjd 230185029Spjd fuid_infop->z_domain_table = 231185029Spjd kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 232185029Spjd 233185029Spjd for (i = 0; i != idcnt; i++) { 234185029Spjd zfs_fuid_t *zfuid; 235185029Spjd 236185029Spjd zfuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP); 237185029Spjd zfuid->z_logfuid = *log_fuid; 238185029Spjd zfuid->z_id = -1; 239185029Spjd zfuid->z_domidx = 0; 240185029Spjd list_insert_tail(&fuid_infop->z_fuids, zfuid); 241185029Spjd log_fuid++; 242185029Spjd } 243185029Spjd 244185029Spjd zfs_replay_fuid_ugid(fuid_infop, uid, gid); 245185029Spjd 246185029Spjd *end = zfs_replay_fuid_domain_common(fuid_infop, log_fuid, domcnt); 247185029Spjd return (fuid_infop); 248185029Spjd} 249185029Spjd 250185029Spjdstatic void 251185029Spjdzfs_replay_swap_attrs(lr_attr_t *lrattr) 252185029Spjd{ 253185029Spjd /* swap the lr_attr structure */ 254185029Spjd byteswap_uint32_array(lrattr, sizeof (*lrattr)); 255185029Spjd /* swap the bitmap */ 256185029Spjd byteswap_uint32_array(lrattr + 1, (lrattr->lr_attr_masksize - 1) * 257185029Spjd sizeof (uint32_t)); 258185029Spjd /* swap the attributes, create time + 64 bit word for attributes */ 259185029Spjd byteswap_uint64_array((caddr_t)(lrattr + 1) + (sizeof (uint32_t) * 260185029Spjd (lrattr->lr_attr_masksize - 1)), 3 * sizeof (uint64_t)); 261185029Spjd} 262185029Spjd 263185029Spjd/* 264185029Spjd * Replay file create with optional ACL, xvattr information as well 265185029Spjd * as option FUID information. 266185029Spjd */ 267185029Spjdstatic int 268185029Spjdzfs_replay_create_acl(zfsvfs_t *zfsvfs, 269185029Spjd lr_acl_create_t *lracl, boolean_t byteswap) 270185029Spjd{ 271185029Spjd char *name = NULL; /* location determined later */ 272185029Spjd lr_create_t *lr = (lr_create_t *)lracl; 273185029Spjd znode_t *dzp; 274185029Spjd vnode_t *vp = NULL; 275185029Spjd xvattr_t xva; 276185029Spjd int vflg = 0; 277185029Spjd vsecattr_t vsec = { 0 }; 278185029Spjd lr_attr_t *lrattr; 279185029Spjd void *aclstart; 280185029Spjd void *fuidstart; 281185029Spjd size_t xvatlen = 0; 282185029Spjd uint64_t txtype; 283185029Spjd int error; 284185029Spjd 285209962Smm txtype = (lr->lr_common.lrc_txtype & ~TX_CI); 286185029Spjd if (byteswap) { 287185029Spjd byteswap_uint64_array(lracl, sizeof (*lracl)); 288185029Spjd if (txtype == TX_CREATE_ACL_ATTR || 289185029Spjd txtype == TX_MKDIR_ACL_ATTR) { 290185029Spjd lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 291185029Spjd zfs_replay_swap_attrs(lrattr); 292185029Spjd xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 293185029Spjd } 294185029Spjd 295185029Spjd aclstart = (caddr_t)(lracl + 1) + xvatlen; 296185029Spjd zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); 297185029Spjd /* swap fuids */ 298185029Spjd if (lracl->lr_fuidcnt) { 299185029Spjd byteswap_uint64_array((caddr_t)aclstart + 300185029Spjd ZIL_ACE_LENGTH(lracl->lr_acl_bytes), 301185029Spjd lracl->lr_fuidcnt * sizeof (uint64_t)); 302185029Spjd } 303185029Spjd } 304185029Spjd 305185029Spjd if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 306185029Spjd return (error); 307185029Spjd 308185029Spjd xva_init(&xva); 309185029Spjd zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 310185029Spjd lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 311185029Spjd 312185029Spjd /* 313185029Spjd * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 314185029Spjd * eventually end up in zfs_mknode(), which assigns the object's 315185029Spjd * creation time and generation number. The generic VOP_CREATE() 316185029Spjd * doesn't have either concept, so we smuggle the values inside 317185029Spjd * the vattr's otherwise unused va_ctime and va_nblocks fields. 318185029Spjd */ 319185029Spjd ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 320185029Spjd xva.xva_vattr.va_nblocks = lr->lr_gen; 321185029Spjd 322185029Spjd error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 323185029Spjd if (error != ENOENT) 324185029Spjd goto bail; 325185029Spjd 326185029Spjd if (lr->lr_common.lrc_txtype & TX_CI) 327185029Spjd vflg |= FIGNORECASE; 328209962Smm switch (txtype) { 329185029Spjd case TX_CREATE_ACL: 330185029Spjd aclstart = (caddr_t)(lracl + 1); 331185029Spjd fuidstart = (caddr_t)aclstart + 332185029Spjd ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 333185029Spjd zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 334185029Spjd (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 335185029Spjd lr->lr_uid, lr->lr_gid); 336185029Spjd /*FALLTHROUGH*/ 337185029Spjd case TX_CREATE_ACL_ATTR: 338185029Spjd if (name == NULL) { 339185029Spjd lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 340185029Spjd xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 341185029Spjd xva.xva_vattr.va_mask |= AT_XVATTR; 342185029Spjd zfs_replay_xvattr(lrattr, &xva); 343185029Spjd } 344185029Spjd vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 345185029Spjd vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 346185029Spjd vsec.vsa_aclcnt = lracl->lr_aclcnt; 347185029Spjd vsec.vsa_aclentsz = lracl->lr_acl_bytes; 348185029Spjd vsec.vsa_aclflags = lracl->lr_acl_flags; 349185029Spjd if (zfsvfs->z_fuid_replay == NULL) { 350185029Spjd fuidstart = (caddr_t)(lracl + 1) + xvatlen + 351185029Spjd ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 352185029Spjd zfsvfs->z_fuid_replay = 353185029Spjd zfs_replay_fuids(fuidstart, 354185029Spjd (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 355185029Spjd lr->lr_uid, lr->lr_gid); 356185029Spjd } 357185029Spjd 358185029Spjd#ifdef TODO 359185029Spjd error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 360185029Spjd 0, 0, &vp, kcred, vflg, NULL, &vsec); 361185029Spjd#else 362185029Spjd panic("%s:%u: unsupported condition", __func__, __LINE__); 363185029Spjd#endif 364185029Spjd break; 365185029Spjd case TX_MKDIR_ACL: 366185029Spjd aclstart = (caddr_t)(lracl + 1); 367185029Spjd fuidstart = (caddr_t)aclstart + 368185029Spjd ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 369185029Spjd zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 370185029Spjd (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 371185029Spjd lr->lr_uid, lr->lr_gid); 372185029Spjd /*FALLTHROUGH*/ 373185029Spjd case TX_MKDIR_ACL_ATTR: 374185029Spjd if (name == NULL) { 375185029Spjd lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 376185029Spjd xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 377185029Spjd zfs_replay_xvattr(lrattr, &xva); 378185029Spjd } 379185029Spjd vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 380185029Spjd vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 381185029Spjd vsec.vsa_aclcnt = lracl->lr_aclcnt; 382185029Spjd vsec.vsa_aclentsz = lracl->lr_acl_bytes; 383185029Spjd vsec.vsa_aclflags = lracl->lr_acl_flags; 384185029Spjd if (zfsvfs->z_fuid_replay == NULL) { 385185029Spjd fuidstart = (caddr_t)(lracl + 1) + xvatlen + 386185029Spjd ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 387185029Spjd zfsvfs->z_fuid_replay = 388185029Spjd zfs_replay_fuids(fuidstart, 389185029Spjd (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 390185029Spjd lr->lr_uid, lr->lr_gid); 391185029Spjd } 392185029Spjd#ifdef TODO 393185029Spjd error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, 394185029Spjd &vp, kcred, NULL, vflg, &vsec); 395185029Spjd#else 396185029Spjd panic("%s:%u: unsupported condition", __func__, __LINE__); 397185029Spjd#endif 398185029Spjd break; 399185029Spjd default: 400249195Smm error = SET_ERROR(ENOTSUP); 401185029Spjd } 402185029Spjd 403185029Spjdbail: 404185029Spjd if (error == 0 && vp != NULL) 405185029Spjd VN_RELE(vp); 406185029Spjd 407185029Spjd VN_RELE(ZTOV(dzp)); 408185029Spjd 409209962Smm if (zfsvfs->z_fuid_replay) 410209962Smm zfs_fuid_info_free(zfsvfs->z_fuid_replay); 411185029Spjd zfsvfs->z_fuid_replay = NULL; 412185029Spjd 413185029Spjd return (error); 414185029Spjd} 415185029Spjd 416185029Spjdstatic int 417168404Spjdzfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) 418168404Spjd{ 419185029Spjd char *name = NULL; /* location determined later */ 420168404Spjd char *link; /* symlink content follows name */ 421168404Spjd znode_t *dzp; 422168404Spjd vnode_t *vp = NULL; 423185029Spjd xvattr_t xva; 424185029Spjd int vflg = 0; 425185029Spjd size_t lrsize = sizeof (lr_create_t); 426185029Spjd lr_attr_t *lrattr; 427185029Spjd void *start; 428185029Spjd size_t xvatlen; 429185029Spjd uint64_t txtype; 430168404Spjd struct componentname cn; 431168404Spjd int error; 432168404Spjd 433209962Smm txtype = (lr->lr_common.lrc_txtype & ~TX_CI); 434185029Spjd if (byteswap) { 435168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 436185029Spjd if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) 437185029Spjd zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 438185029Spjd } 439168404Spjd 440185029Spjd 441168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 442168404Spjd return (error); 443168404Spjd 444185029Spjd xva_init(&xva); 445185029Spjd zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 446168404Spjd lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 447168404Spjd 448168404Spjd /* 449168404Spjd * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 450168404Spjd * eventually end up in zfs_mknode(), which assigns the object's 451168404Spjd * creation time and generation number. The generic VOP_CREATE() 452168404Spjd * doesn't have either concept, so we smuggle the values inside 453168404Spjd * the vattr's otherwise unused va_ctime and va_nblocks fields. 454168404Spjd */ 455185029Spjd ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 456185029Spjd xva.xva_vattr.va_nblocks = lr->lr_gen; 457168404Spjd 458185029Spjd error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 459185029Spjd if (error != ENOENT) 460185029Spjd goto out; 461185029Spjd 462185029Spjd if (lr->lr_common.lrc_txtype & TX_CI) 463185029Spjd vflg |= FIGNORECASE; 464185029Spjd 465185029Spjd /* 466185029Spjd * Symlinks don't have fuid info, and CIFS never creates 467185029Spjd * symlinks. 468185029Spjd * 469185029Spjd * The _ATTR versions will grab the fuid info in their subcases. 470185029Spjd */ 471185029Spjd if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK && 472185029Spjd (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR && 473185029Spjd (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) { 474185029Spjd start = (lr + 1); 475185029Spjd zfsvfs->z_fuid_replay = 476185029Spjd zfs_replay_fuid_domain(start, &start, 477185029Spjd lr->lr_uid, lr->lr_gid); 478185029Spjd } 479185029Spjd 480168404Spjd cn.cn_cred = kcred; 481168404Spjd cn.cn_thread = curthread; 482168404Spjd cn.cn_flags = SAVENAME; 483168404Spjd 484175202Sattilio vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); 485209962Smm switch (txtype) { 486185029Spjd case TX_CREATE_ATTR: 487185029Spjd lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 488185029Spjd xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 489185029Spjd zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 490185029Spjd start = (caddr_t)(lr + 1) + xvatlen; 491185029Spjd zfsvfs->z_fuid_replay = 492185029Spjd zfs_replay_fuid_domain(start, &start, 493185029Spjd lr->lr_uid, lr->lr_gid); 494185029Spjd name = (char *)start; 495185029Spjd 496185029Spjd /*FALLTHROUGH*/ 497168404Spjd case TX_CREATE: 498185029Spjd if (name == NULL) 499185029Spjd name = (char *)start; 500185029Spjd 501185029Spjd cn.cn_nameptr = name; 502185029Spjd error = VOP_CREATE(ZTOV(dzp), &vp, &cn, &xva.xva_vattr /*,vflg*/); 503168404Spjd break; 504185029Spjd case TX_MKDIR_ATTR: 505185029Spjd lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 506185029Spjd xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 507185029Spjd zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 508185029Spjd start = (caddr_t)(lr + 1) + xvatlen; 509185029Spjd zfsvfs->z_fuid_replay = 510185029Spjd zfs_replay_fuid_domain(start, &start, 511185029Spjd lr->lr_uid, lr->lr_gid); 512185029Spjd name = (char *)start; 513185029Spjd 514185029Spjd /*FALLTHROUGH*/ 515168404Spjd case TX_MKDIR: 516185029Spjd if (name == NULL) 517185029Spjd name = (char *)(lr + 1); 518185029Spjd 519185029Spjd cn.cn_nameptr = name; 520185029Spjd error = VOP_MKDIR(ZTOV(dzp), &vp, &cn, &xva.xva_vattr /*,vflg*/); 521168404Spjd break; 522168404Spjd case TX_MKXATTR: 523185029Spjd error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &vp, kcred); 524168404Spjd break; 525168404Spjd case TX_SYMLINK: 526185029Spjd name = (char *)(lr + 1); 527168404Spjd link = name + strlen(name) + 1; 528185029Spjd cn.cn_nameptr = name; 529185029Spjd error = VOP_SYMLINK(ZTOV(dzp), &vp, &cn, &xva.xva_vattr, link /*,vflg*/); 530168404Spjd break; 531168404Spjd default: 532249195Smm error = SET_ERROR(ENOTSUP); 533168404Spjd } 534175294Sattilio VOP_UNLOCK(ZTOV(dzp), 0); 535168404Spjd 536185029Spjdout: 537219089Spjd if (error == 0 && vp != NULL) 538219089Spjd VN_URELE(vp); 539168404Spjd 540168404Spjd VN_RELE(ZTOV(dzp)); 541168404Spjd 542185029Spjd if (zfsvfs->z_fuid_replay) 543185029Spjd zfs_fuid_info_free(zfsvfs->z_fuid_replay); 544185029Spjd zfsvfs->z_fuid_replay = NULL; 545168404Spjd return (error); 546168404Spjd} 547168404Spjd 548168404Spjdstatic int 549168404Spjdzfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap) 550168404Spjd{ 551168404Spjd char *name = (char *)(lr + 1); /* name follows lr_remove_t */ 552168404Spjd znode_t *dzp; 553168404Spjd struct componentname cn; 554168404Spjd vnode_t *vp; 555168404Spjd int error; 556185029Spjd int vflg = 0; 557168404Spjd 558168404Spjd if (byteswap) 559168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 560168404Spjd 561168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 562168404Spjd return (error); 563168404Spjd 564185029Spjd if (lr->lr_common.lrc_txtype & TX_CI) 565185029Spjd vflg |= FIGNORECASE; 566168404Spjd cn.cn_nameptr = name; 567168404Spjd cn.cn_namelen = strlen(name); 568168404Spjd cn.cn_nameiop = DELETE; 569168404Spjd cn.cn_flags = ISLASTCN | SAVENAME; 570169884Spjd cn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 571168404Spjd cn.cn_cred = kcred; 572168404Spjd cn.cn_thread = curthread; 573175202Sattilio vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); 574168404Spjd error = VOP_LOOKUP(ZTOV(dzp), &vp, &cn); 575168404Spjd if (error != 0) { 576175294Sattilio VOP_UNLOCK(ZTOV(dzp), 0); 577168404Spjd goto fail; 578168404Spjd } 579168404Spjd 580168404Spjd switch ((int)lr->lr_common.lrc_txtype) { 581168404Spjd case TX_REMOVE: 582185029Spjd error = VOP_REMOVE(ZTOV(dzp), vp, &cn /*,vflg*/); 583168404Spjd break; 584168404Spjd case TX_RMDIR: 585185029Spjd error = VOP_RMDIR(ZTOV(dzp), vp, &cn /*,vflg*/); 586168404Spjd break; 587168404Spjd default: 588249195Smm error = SET_ERROR(ENOTSUP); 589168404Spjd } 590168404Spjd vput(vp); 591175294Sattilio VOP_UNLOCK(ZTOV(dzp), 0); 592219089Spjd 593168404Spjdfail: 594168404Spjd VN_RELE(ZTOV(dzp)); 595168404Spjd 596168404Spjd return (error); 597168404Spjd} 598168404Spjd 599168404Spjdstatic int 600168404Spjdzfs_replay_link(zfsvfs_t *zfsvfs, lr_link_t *lr, boolean_t byteswap) 601168404Spjd{ 602168404Spjd char *name = (char *)(lr + 1); /* name follows lr_link_t */ 603168404Spjd znode_t *dzp, *zp; 604168404Spjd struct componentname cn; 605168404Spjd int error; 606185029Spjd int vflg = 0; 607168404Spjd 608168404Spjd if (byteswap) 609168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 610168404Spjd 611168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 612168404Spjd return (error); 613168404Spjd 614168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_link_obj, &zp)) != 0) { 615168404Spjd VN_RELE(ZTOV(dzp)); 616168404Spjd return (error); 617168404Spjd } 618168404Spjd 619185029Spjd if (lr->lr_common.lrc_txtype & TX_CI) 620185029Spjd vflg |= FIGNORECASE; 621219089Spjd 622168404Spjd cn.cn_nameptr = name; 623168404Spjd cn.cn_cred = kcred; 624168404Spjd cn.cn_thread = curthread; 625168404Spjd cn.cn_flags = SAVENAME; 626168404Spjd 627175202Sattilio vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); 628175202Sattilio vn_lock(ZTOV(zp), LK_EXCLUSIVE | LK_RETRY); 629185029Spjd error = VOP_LINK(ZTOV(dzp), ZTOV(zp), &cn /*,vflg*/); 630175294Sattilio VOP_UNLOCK(ZTOV(zp), 0); 631175294Sattilio VOP_UNLOCK(ZTOV(dzp), 0); 632168404Spjd 633168404Spjd VN_RELE(ZTOV(zp)); 634168404Spjd VN_RELE(ZTOV(dzp)); 635168404Spjd 636168404Spjd return (error); 637168404Spjd} 638168404Spjd 639168404Spjdstatic int 640168404Spjdzfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap) 641168404Spjd{ 642168404Spjd char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ 643168404Spjd char *tname = sname + strlen(sname) + 1; 644168404Spjd znode_t *sdzp, *tdzp; 645168404Spjd struct componentname scn, tcn; 646168404Spjd vnode_t *svp, *tvp; 647168404Spjd kthread_t *td = curthread; 648168404Spjd int error; 649185029Spjd int vflg = 0; 650168404Spjd 651168404Spjd if (byteswap) 652168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 653168404Spjd 654168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) 655168404Spjd return (error); 656168404Spjd 657168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { 658168404Spjd VN_RELE(ZTOV(sdzp)); 659168404Spjd return (error); 660168404Spjd } 661168404Spjd 662185029Spjd if (lr->lr_common.lrc_txtype & TX_CI) 663185029Spjd vflg |= FIGNORECASE; 664168404Spjd svp = tvp = NULL; 665168404Spjd 666168404Spjd scn.cn_nameptr = sname; 667168404Spjd scn.cn_namelen = strlen(sname); 668168404Spjd scn.cn_nameiop = DELETE; 669168404Spjd scn.cn_flags = ISLASTCN | SAVENAME; 670169884Spjd scn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 671168404Spjd scn.cn_cred = kcred; 672168404Spjd scn.cn_thread = td; 673175202Sattilio vn_lock(ZTOV(sdzp), LK_EXCLUSIVE | LK_RETRY); 674168404Spjd error = VOP_LOOKUP(ZTOV(sdzp), &svp, &scn); 675175294Sattilio VOP_UNLOCK(ZTOV(sdzp), 0); 676168404Spjd if (error != 0) 677168404Spjd goto fail; 678175294Sattilio VOP_UNLOCK(svp, 0); 679168404Spjd 680168404Spjd tcn.cn_nameptr = tname; 681168404Spjd tcn.cn_namelen = strlen(tname); 682168404Spjd tcn.cn_nameiop = RENAME; 683168404Spjd tcn.cn_flags = ISLASTCN | SAVENAME; 684169884Spjd tcn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 685168404Spjd tcn.cn_cred = kcred; 686168404Spjd tcn.cn_thread = td; 687175202Sattilio vn_lock(ZTOV(tdzp), LK_EXCLUSIVE | LK_RETRY); 688168404Spjd error = VOP_LOOKUP(ZTOV(tdzp), &tvp, &tcn); 689168404Spjd if (error == EJUSTRETURN) 690168404Spjd tvp = NULL; 691168404Spjd else if (error != 0) { 692175294Sattilio VOP_UNLOCK(ZTOV(tdzp), 0); 693168404Spjd goto fail; 694168404Spjd } 695168404Spjd 696185029Spjd error = VOP_RENAME(ZTOV(sdzp), svp, &scn, ZTOV(tdzp), tvp, &tcn /*,vflg*/); 697168404Spjd return (error); 698168404Spjdfail: 699168404Spjd if (svp != NULL) 700168404Spjd vrele(svp); 701168404Spjd if (tvp != NULL) 702168404Spjd vrele(tvp); 703168404Spjd VN_RELE(ZTOV(tdzp)); 704168404Spjd VN_RELE(ZTOV(sdzp)); 705168404Spjd 706168404Spjd return (error); 707168404Spjd} 708168404Spjd 709168404Spjdstatic int 710168404Spjdzfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 711168404Spjd{ 712168404Spjd char *data = (char *)(lr + 1); /* data follows lr_write_t */ 713168404Spjd znode_t *zp; 714168404Spjd int error; 715168404Spjd ssize_t resid; 716219089Spjd uint64_t eod, offset, length; 717168404Spjd 718168404Spjd if (byteswap) 719168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 720168404Spjd 721168404Spjd if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 722168404Spjd /* 723168404Spjd * As we can log writes out of order, it's possible the 724168404Spjd * file has been removed. In this case just drop the write 725168404Spjd * and return success. 726168404Spjd */ 727168404Spjd if (error == ENOENT) 728168404Spjd error = 0; 729168404Spjd return (error); 730168404Spjd } 731168404Spjd 732219089Spjd offset = lr->lr_offset; 733219089Spjd length = lr->lr_length; 734219089Spjd eod = offset + length; /* end of data for this write */ 735209962Smm 736209962Smm /* 737209962Smm * This may be a write from a dmu_sync() for a whole block, 738209962Smm * and may extend beyond the current end of the file. 739209962Smm * We can't just replay what was written for this TX_WRITE as 740209962Smm * a future TX_WRITE2 may extend the eof and the data for that 741209962Smm * write needs to be there. So we write the whole block and 742219089Spjd * reduce the eof. This needs to be done within the single dmu 743219089Spjd * transaction created within vn_rdwr -> zfs_write. So a possible 744219089Spjd * new end of file is passed through in zfsvfs->z_replay_eof 745209962Smm */ 746209962Smm 747219089Spjd zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */ 748219089Spjd 749219089Spjd /* If it's a dmu_sync() block, write the whole block */ 750219089Spjd if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { 751219089Spjd uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr); 752219089Spjd if (length < blocksize) { 753219089Spjd offset -= offset % blocksize; 754219089Spjd length = blocksize; 755219089Spjd } 756219089Spjd if (zp->z_size < eod) 757219089Spjd zfsvfs->z_replay_eof = eod; 758219089Spjd } 759219089Spjd 760219089Spjd error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset, 761219089Spjd UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); 762219089Spjd 763168404Spjd VN_RELE(ZTOV(zp)); 764219089Spjd zfsvfs->z_replay_eof = 0; /* safety */ 765168404Spjd 766168404Spjd return (error); 767168404Spjd} 768168404Spjd 769209962Smm/* 770209962Smm * TX_WRITE2 are only generated when dmu_sync() returns EALREADY 771209962Smm * meaning the pool block is already being synced. So now that we always write 772209962Smm * out full blocks, all we have to do is expand the eof if 773209962Smm * the file is grown. 774209962Smm */ 775168404Spjdstatic int 776209962Smmzfs_replay_write2(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 777209962Smm{ 778209962Smm znode_t *zp; 779209962Smm int error; 780209962Smm uint64_t end; 781209962Smm 782209962Smm if (byteswap) 783209962Smm byteswap_uint64_array(lr, sizeof (*lr)); 784209962Smm 785219089Spjd if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 786209962Smm return (error); 787209962Smm 788219089Spjdtop: 789209962Smm end = lr->lr_offset + lr->lr_length; 790219089Spjd if (end > zp->z_size) { 791219089Spjd dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 792219089Spjd 793219089Spjd zp->z_size = end; 794219089Spjd dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 795219089Spjd error = dmu_tx_assign(tx, TXG_WAIT); 796219089Spjd if (error) { 797219089Spjd VN_RELE(ZTOV(zp)); 798219089Spjd if (error == ERESTART) { 799219089Spjd dmu_tx_wait(tx); 800219089Spjd dmu_tx_abort(tx); 801219089Spjd goto top; 802219089Spjd } 803219089Spjd dmu_tx_abort(tx); 804219089Spjd return (error); 805219089Spjd } 806219089Spjd (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), 807219089Spjd (void *)&zp->z_size, sizeof (uint64_t), tx); 808219089Spjd 809219089Spjd /* Ensure the replayed seq is updated */ 810219089Spjd (void) zil_replaying(zfsvfs->z_log, tx); 811219089Spjd 812219089Spjd dmu_tx_commit(tx); 813209962Smm } 814209962Smm 815209962Smm VN_RELE(ZTOV(zp)); 816209962Smm 817209962Smm return (error); 818209962Smm} 819209962Smm 820209962Smmstatic int 821168404Spjdzfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap) 822168404Spjd{ 823219089Spjd#ifdef sun 824219089Spjd znode_t *zp; 825219089Spjd flock64_t fl; 826219089Spjd int error; 827168404Spjd 828219089Spjd if (byteswap) 829219089Spjd byteswap_uint64_array(lr, sizeof (*lr)); 830219089Spjd 831219089Spjd if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 832219089Spjd return (error); 833219089Spjd 834219089Spjd bzero(&fl, sizeof (fl)); 835219089Spjd fl.l_type = F_WRLCK; 836219089Spjd fl.l_whence = 0; 837219089Spjd fl.l_start = lr->lr_offset; 838219089Spjd fl.l_len = lr->lr_length; 839219089Spjd 840219089Spjd error = VOP_SPACE(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX, 841219089Spjd lr->lr_offset, kcred, NULL); 842219089Spjd 843219089Spjd VN_RELE(ZTOV(zp)); 844219089Spjd 845219089Spjd return (error); 846219089Spjd#else /* !sun */ 847168404Spjd ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); 848168404Spjd return (EOPNOTSUPP); 849219089Spjd#endif /* !sun */ 850168404Spjd} 851168404Spjd 852168404Spjdstatic int 853168404Spjdzfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap) 854168404Spjd{ 855168404Spjd znode_t *zp; 856185029Spjd xvattr_t xva; 857185029Spjd vattr_t *vap = &xva.xva_vattr; 858168404Spjd vnode_t *vp; 859168404Spjd int error; 860185029Spjd void *start; 861168404Spjd 862185029Spjd xva_init(&xva); 863185029Spjd if (byteswap) { 864168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 865168404Spjd 866185029Spjd if ((lr->lr_mask & AT_XVATTR) && 867185029Spjd zfsvfs->z_version >= ZPL_VERSION_INITIAL) 868185029Spjd zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 869185029Spjd } 870185029Spjd 871219089Spjd if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 872168404Spjd return (error); 873168404Spjd 874185029Spjd zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, 875168404Spjd lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); 876168404Spjd 877185029Spjd vap->va_size = lr->lr_size; 878185029Spjd ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); 879185029Spjd ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); 880168404Spjd 881185029Spjd /* 882185029Spjd * Fill in xvattr_t portions if necessary. 883185029Spjd */ 884185029Spjd 885185029Spjd start = (lr_setattr_t *)(lr + 1); 886185029Spjd if (vap->va_mask & AT_XVATTR) { 887185029Spjd zfs_replay_xvattr((lr_attr_t *)start, &xva); 888185029Spjd start = (caddr_t)start + 889185029Spjd ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); 890185029Spjd } else 891185029Spjd xva.xva_vattr.va_mask &= ~AT_XVATTR; 892185029Spjd 893185029Spjd zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, 894185029Spjd lr->lr_uid, lr->lr_gid); 895185029Spjd 896168404Spjd vp = ZTOV(zp); 897175202Sattilio vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 898185029Spjd error = VOP_SETATTR(vp, vap, kcred); 899175294Sattilio VOP_UNLOCK(vp, 0); 900185029Spjd 901185029Spjd zfs_fuid_info_free(zfsvfs->z_fuid_replay); 902185029Spjd zfsvfs->z_fuid_replay = NULL; 903168404Spjd VN_RELE(vp); 904168404Spjd 905168404Spjd return (error); 906168404Spjd} 907168404Spjd 908228685Spjdextern int zfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr, 909228685Spjd caller_context_t *ct); 910228685Spjd 911168404Spjdstatic int 912185029Spjdzfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap) 913168404Spjd{ 914168404Spjd ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */ 915185029Spjd vsecattr_t vsa; 916228685Spjd vnode_t *vp; 917185029Spjd znode_t *zp; 918185029Spjd int error; 919185029Spjd 920185029Spjd if (byteswap) { 921185029Spjd byteswap_uint64_array(lr, sizeof (*lr)); 922185029Spjd zfs_oldace_byteswap(ace, lr->lr_aclcnt); 923185029Spjd } 924185029Spjd 925219089Spjd if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 926185029Spjd return (error); 927185029Spjd 928185029Spjd bzero(&vsa, sizeof (vsa)); 929185029Spjd vsa.vsa_mask = VSA_ACE | VSA_ACECNT; 930185029Spjd vsa.vsa_aclcnt = lr->lr_aclcnt; 931185029Spjd vsa.vsa_aclentsz = sizeof (ace_t) * vsa.vsa_aclcnt; 932185029Spjd vsa.vsa_aclflags = 0; 933185029Spjd vsa.vsa_aclentp = ace; 934185029Spjd 935228685Spjd vp = ZTOV(zp); 936228685Spjd vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 937228685Spjd error = zfs_setsecattr(vp, &vsa, 0, kcred, NULL); 938228685Spjd VOP_UNLOCK(vp, 0); 939185029Spjd 940228685Spjd VN_RELE(vp); 941185029Spjd 942185029Spjd return (error); 943185029Spjd} 944185029Spjd 945185029Spjd/* 946185029Spjd * Replaying ACLs is complicated by FUID support. 947185029Spjd * The log record may contain some optional data 948185029Spjd * to be used for replaying FUID's. These pieces 949185029Spjd * are the actual FUIDs that were created initially. 950185029Spjd * The FUID table index may no longer be valid and 951185029Spjd * during zfs_create() a new index may be assigned. 952185029Spjd * Because of this the log will contain the original 953185029Spjd * doman+rid in order to create a new FUID. 954185029Spjd * 955185029Spjd * The individual ACEs may contain an ephemeral uid/gid which is no 956185029Spjd * longer valid and will need to be replaced with an actual FUID. 957185029Spjd * 958185029Spjd */ 959185029Spjdstatic int 960185029Spjdzfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap) 961185029Spjd{ 962185029Spjd ace_t *ace = (ace_t *)(lr + 1); 963168404Spjd vsecattr_t vsa; 964168404Spjd znode_t *zp; 965228685Spjd vnode_t *vp; 966168404Spjd int error; 967168404Spjd 968168404Spjd if (byteswap) { 969168404Spjd byteswap_uint64_array(lr, sizeof (*lr)); 970185029Spjd zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE); 971185029Spjd if (lr->lr_fuidcnt) { 972185029Spjd byteswap_uint64_array((caddr_t)ace + 973185029Spjd ZIL_ACE_LENGTH(lr->lr_acl_bytes), 974185029Spjd lr->lr_fuidcnt * sizeof (uint64_t)); 975185029Spjd } 976168404Spjd } 977168404Spjd 978219089Spjd if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 979168404Spjd return (error); 980168404Spjd 981168404Spjd bzero(&vsa, sizeof (vsa)); 982185029Spjd vsa.vsa_mask = VSA_ACE | VSA_ACECNT | VSA_ACE_ACLFLAGS; 983168404Spjd vsa.vsa_aclcnt = lr->lr_aclcnt; 984168404Spjd vsa.vsa_aclentp = ace; 985185029Spjd vsa.vsa_aclentsz = lr->lr_acl_bytes; 986185029Spjd vsa.vsa_aclflags = lr->lr_acl_flags; 987168404Spjd 988185029Spjd if (lr->lr_fuidcnt) { 989185029Spjd void *fuidstart = (caddr_t)ace + 990185029Spjd ZIL_ACE_LENGTH(lr->lr_acl_bytes); 991185029Spjd 992185029Spjd zfsvfs->z_fuid_replay = 993185029Spjd zfs_replay_fuids(fuidstart, &fuidstart, 994185029Spjd lr->lr_fuidcnt, lr->lr_domcnt, 0, 0); 995185029Spjd } 996185029Spjd 997228685Spjd vp = ZTOV(zp); 998228685Spjd vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 999228685Spjd error = zfs_setsecattr(vp, &vsa, 0, kcred, NULL); 1000228685Spjd VOP_UNLOCK(vp, 0); 1001185029Spjd 1002185029Spjd if (zfsvfs->z_fuid_replay) 1003185029Spjd zfs_fuid_info_free(zfsvfs->z_fuid_replay); 1004168404Spjd 1005185029Spjd zfsvfs->z_fuid_replay = NULL; 1006228685Spjd VN_RELE(vp); 1007168404Spjd 1008168404Spjd return (error); 1009168404Spjd} 1010168404Spjd 1011168404Spjd/* 1012168404Spjd * Callback vectors for replaying records 1013168404Spjd */ 1014168404Spjdzil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE] = { 1015168404Spjd zfs_replay_error, /* 0 no such transaction type */ 1016168404Spjd zfs_replay_create, /* TX_CREATE */ 1017168404Spjd zfs_replay_create, /* TX_MKDIR */ 1018168404Spjd zfs_replay_create, /* TX_MKXATTR */ 1019168404Spjd zfs_replay_create, /* TX_SYMLINK */ 1020168404Spjd zfs_replay_remove, /* TX_REMOVE */ 1021168404Spjd zfs_replay_remove, /* TX_RMDIR */ 1022168404Spjd zfs_replay_link, /* TX_LINK */ 1023168404Spjd zfs_replay_rename, /* TX_RENAME */ 1024168404Spjd zfs_replay_write, /* TX_WRITE */ 1025168404Spjd zfs_replay_truncate, /* TX_TRUNCATE */ 1026168404Spjd zfs_replay_setattr, /* TX_SETATTR */ 1027185029Spjd zfs_replay_acl_v0, /* TX_ACL_V0 */ 1028168404Spjd zfs_replay_acl, /* TX_ACL */ 1029185029Spjd zfs_replay_create_acl, /* TX_CREATE_ACL */ 1030185029Spjd zfs_replay_create, /* TX_CREATE_ATTR */ 1031185029Spjd zfs_replay_create_acl, /* TX_CREATE_ACL_ATTR */ 1032185029Spjd zfs_replay_create_acl, /* TX_MKDIR_ACL */ 1033185029Spjd zfs_replay_create, /* TX_MKDIR_ATTR */ 1034185029Spjd zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */ 1035209962Smm zfs_replay_write2, /* TX_WRITE2 */ 1036168404Spjd}; 1037