zfs_replay.c revision 219089
190075Sobrien/* 2169689Skan * CDDL HEADER START 3169689Skan * 490075Sobrien * The contents of this file are subject to the terms of the 590075Sobrien * Common Development and Distribution License (the "License"). 690075Sobrien * You may not use this file except in compliance with the License. 790075Sobrien * 890075Sobrien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 990075Sobrien * or http://www.opensolaris.org/os/licensing. 1090075Sobrien * See the License for the specific language governing permissions 1190075Sobrien * and limitations under the License. 1290075Sobrien * 1390075Sobrien * When distributing Covered Code, include this CDDL HEADER in each 1490075Sobrien * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1590075Sobrien * If applicable, add the following below this CDDL HEADER, with the 1690075Sobrien * fields enclosed by brackets "[]" replaced with your own identifying 1790075Sobrien * information: Portions Copyright [yyyy] [name of copyright owner] 1890075Sobrien * 1990075Sobrien * CDDL HEADER END 20169689Skan */ 21169689Skan/* 2290075Sobrien * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2390075Sobrien */ 2490075Sobrien 25132718Skan#include <sys/types.h> 26132718Skan#include <sys/param.h> 2790075Sobrien#include <sys/systm.h> 2890075Sobrien#include <sys/sysmacros.h> 2990075Sobrien#include <sys/cmn_err.h> 3090075Sobrien#include <sys/kmem.h> 3190075Sobrien#include <sys/file.h> 32169689Skan#include <sys/fcntl.h> 3390075Sobrien#include <sys/vfs.h> 34169689Skan#include <sys/fs/zfs.h> 35169689Skan#include <sys/zfs_znode.h> 3690075Sobrien#include <sys/zfs_dir.h> 37132718Skan#include <sys/zfs_acl.h> 38132718Skan#include <sys/zfs_fuid.h> 39132718Skan#include <sys/spa.h> 40132718Skan#include <sys/zil.h> 41132718Skan#include <sys/byteorder.h> 42169689Skan#include <sys/stat.h> 4390075Sobrien#include <sys/acl.h> 4490075Sobrien#include <sys/atomic.h> 4590075Sobrien#include <sys/cred.h> 4690075Sobrien#include <sys/namei.h> 4790075Sobrien 48132718Skan/* 4990075Sobrien * Functions to replay ZFS intent log (ZIL) records 5090075Sobrien * The functions are called through a function vector (zfs_replay_vector) 5190075Sobrien * which is indexed by the transaction type. 5290075Sobrien */ 5390075Sobrien 5490075Sobrienstatic void 5590075Sobrienzfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode, 5690075Sobrien uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid) 5790075Sobrien{ 5890075Sobrien VATTR_NULL(vap); 5990075Sobrien vap->va_mask = (uint_t)mask; 6090075Sobrien if (mask & AT_TYPE) 6190075Sobrien vap->va_type = IFTOVT(mode); 6290075Sobrien if (mask & AT_MODE) 6390075Sobrien vap->va_mode = mode & MODEMASK; 64169689Skan if (mask & AT_UID) 6590075Sobrien vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; 6690075Sobrien if (mask & AT_GID) 67169689Skan vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; 6890075Sobrien vap->va_rdev = zfs_cmpldev(rdev); 6990075Sobrien vap->va_nodeid = nodeid; 70117395Skan} 7190075Sobrien 7290075Sobrien/* ARGSUSED */ 7390075Sobrienstatic int 7490075Sobrienzfs_replay_error(zfsvfs_t *zfsvfs, lr_t *lr, boolean_t byteswap) 7590075Sobrien{ 7690075Sobrien return (ENOTSUP); 7790075Sobrien} 7890075Sobrien 7990075Sobrienstatic void 8090075Sobrienzfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) 8190075Sobrien{ 8290075Sobrien xoptattr_t *xoap = NULL; 8390075Sobrien uint64_t *attrs; 8490075Sobrien uint64_t *crtime; 8590075Sobrien uint32_t *bitmap; 86132718Skan void *scanstamp; 8790075Sobrien int i; 8890075Sobrien 8990075Sobrien xvap->xva_vattr.va_mask |= AT_XVATTR; 9090075Sobrien if ((xoap = xva_getxoptattr(xvap)) == NULL) { 9190075Sobrien xvap->xva_vattr.va_mask &= ~AT_XVATTR; /* shouldn't happen */ 9290075Sobrien return; 9390075Sobrien } 9490075Sobrien 9590075Sobrien ASSERT(lrattr->lr_attr_masksize == xvap->xva_mapsize); 9690075Sobrien 97132718Skan bitmap = &lrattr->lr_attr_bitmap; 9890075Sobrien for (i = 0; i != lrattr->lr_attr_masksize; i++, bitmap++) 9990075Sobrien xvap->xva_reqattrmap[i] = *bitmap; 10090075Sobrien 10190075Sobrien attrs = (uint64_t *)(lrattr + lrattr->lr_attr_masksize - 1); 10290075Sobrien crtime = attrs + 1; 10390075Sobrien scanstamp = (caddr_t)(crtime + 2); 10490075Sobrien 10590075Sobrien if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) 10690075Sobrien xoap->xoa_hidden = ((*attrs & XAT0_HIDDEN) != 0); 10790075Sobrien if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) 10890075Sobrien xoap->xoa_system = ((*attrs & XAT0_SYSTEM) != 0); 10990075Sobrien if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) 11090075Sobrien xoap->xoa_archive = ((*attrs & XAT0_ARCHIVE) != 0); 11190075Sobrien if (XVA_ISSET_REQ(xvap, XAT_READONLY)) 11290075Sobrien xoap->xoa_readonly = ((*attrs & XAT0_READONLY) != 0); 11390075Sobrien if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) 11490075Sobrien xoap->xoa_immutable = ((*attrs & XAT0_IMMUTABLE) != 0); 11590075Sobrien if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) 11690075Sobrien xoap->xoa_nounlink = ((*attrs & XAT0_NOUNLINK) != 0); 11790075Sobrien if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) 11890075Sobrien xoap->xoa_appendonly = ((*attrs & XAT0_APPENDONLY) != 0); 11990075Sobrien if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) 12090075Sobrien xoap->xoa_nodump = ((*attrs & XAT0_NODUMP) != 0); 12190075Sobrien if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) 12290075Sobrien xoap->xoa_opaque = ((*attrs & XAT0_OPAQUE) != 0); 12390075Sobrien if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) 12490075Sobrien xoap->xoa_av_modified = ((*attrs & XAT0_AV_MODIFIED) != 0); 125132718Skan if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) 12690075Sobrien xoap->xoa_av_quarantined = 12790075Sobrien ((*attrs & XAT0_AV_QUARANTINED) != 0); 12890075Sobrien if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) 12990075Sobrien ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime); 13090075Sobrien if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) 13190075Sobrien bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); 13290075Sobrien if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) 13390075Sobrien xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); 13490075Sobrien if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) 13590075Sobrien xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0); 13690075Sobrien if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) 13790075Sobrien xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); 13890075Sobrien} 139132718Skan 14090075Sobrienstatic int 14190075Sobrienzfs_replay_domain_cnt(uint64_t uid, uint64_t gid) 14290075Sobrien{ 14390075Sobrien uint64_t uid_idx; 14490075Sobrien uint64_t gid_idx; 14590075Sobrien int domcnt = 0; 14690075Sobrien 14790075Sobrien uid_idx = FUID_INDEX(uid); 148132718Skan gid_idx = FUID_INDEX(gid); 14990075Sobrien if (uid_idx) 15090075Sobrien domcnt++; 151117395Skan if (gid_idx > 0 && gid_idx != uid_idx) 15290075Sobrien domcnt++; 15390075Sobrien 15490075Sobrien return (domcnt); 15590075Sobrien} 15690075Sobrien 15790075Sobrienstatic void * 15890075Sobrienzfs_replay_fuid_domain_common(zfs_fuid_info_t *fuid_infop, void *start, 15990075Sobrien int domcnt) 16090075Sobrien{ 16190075Sobrien int i; 16290075Sobrien 16390075Sobrien for (i = 0; i != domcnt; i++) { 16490075Sobrien fuid_infop->z_domain_table[i] = start; 16590075Sobrien start = (caddr_t)start + strlen(start) + 1; 166132718Skan } 16790075Sobrien 16890075Sobrien return (start); 16990075Sobrien} 17090075Sobrien 17190075Sobrien/* 17290075Sobrien * Set the uid/gid in the fuid_info structure. 17390075Sobrien */ 17490075Sobrienstatic void 17590075Sobrienzfs_replay_fuid_ugid(zfs_fuid_info_t *fuid_infop, uint64_t uid, uint64_t gid) 176132718Skan{ 17790075Sobrien /* 17890075Sobrien * If owner or group are log specific FUIDs then slurp up 17990075Sobrien * domain information and build zfs_fuid_info_t 18090075Sobrien */ 18190075Sobrien if (IS_EPHEMERAL(uid)) 18290075Sobrien fuid_infop->z_fuid_owner = uid; 183169689Skan 184169689Skan if (IS_EPHEMERAL(gid)) 185169689Skan fuid_infop->z_fuid_group = gid; 186169689Skan} 187169689Skan 188169689Skan/* 189169689Skan * Load fuid domains into fuid_info_t 190169689Skan */ 191169689Skanstatic zfs_fuid_info_t * 192169689Skanzfs_replay_fuid_domain(void *buf, void **end, uint64_t uid, uint64_t gid) 193169689Skan{ 194169689Skan int domcnt; 195169689Skan 19690075Sobrien zfs_fuid_info_t *fuid_infop; 19790075Sobrien 19890075Sobrien fuid_infop = zfs_fuid_info_alloc(); 199132718Skan 20090075Sobrien domcnt = zfs_replay_domain_cnt(uid, gid); 20190075Sobrien 20290075Sobrien if (domcnt == 0) 20390075Sobrien return (fuid_infop); 20490075Sobrien 20590075Sobrien fuid_infop->z_domain_table = 20690075Sobrien kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 20790075Sobrien 20890075Sobrien zfs_replay_fuid_ugid(fuid_infop, uid, gid); 20990075Sobrien 21090075Sobrien fuid_infop->z_domain_cnt = domcnt; 211169689Skan *end = zfs_replay_fuid_domain_common(fuid_infop, buf, domcnt); 212132718Skan return (fuid_infop); 21390075Sobrien} 21490075Sobrien 21590075Sobrien/* 21690075Sobrien * load zfs_fuid_t's and fuid_domains into fuid_info_t 21790075Sobrien */ 21890075Sobrienstatic zfs_fuid_info_t * 21990075Sobrienzfs_replay_fuids(void *start, void **end, int idcnt, int domcnt, uint64_t uid, 22090075Sobrien uint64_t gid) 22190075Sobrien{ 22290075Sobrien uint64_t *log_fuid = (uint64_t *)start; 22390075Sobrien zfs_fuid_info_t *fuid_infop; 224117395Skan int i; 225132718Skan 22690075Sobrien fuid_infop = zfs_fuid_info_alloc(); 22790075Sobrien fuid_infop->z_domain_cnt = domcnt; 22890075Sobrien 22990075Sobrien fuid_infop->z_domain_table = 23090075Sobrien kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP); 23190075Sobrien 23290075Sobrien for (i = 0; i != idcnt; i++) { 233169689Skan zfs_fuid_t *zfuid; 23490075Sobrien 23590075Sobrien zfuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP); 23690075Sobrien zfuid->z_logfuid = *log_fuid; 23790075Sobrien zfuid->z_id = -1; 23890075Sobrien zfuid->z_domidx = 0; 23990075Sobrien list_insert_tail(&fuid_infop->z_fuids, zfuid); 24090075Sobrien log_fuid++; 24190075Sobrien } 24290075Sobrien 24390075Sobrien zfs_replay_fuid_ugid(fuid_infop, uid, gid); 24490075Sobrien 24590075Sobrien *end = zfs_replay_fuid_domain_common(fuid_infop, log_fuid, domcnt); 24690075Sobrien return (fuid_infop); 24790075Sobrien} 24890075Sobrien 24990075Sobrienstatic void 25090075Sobrienzfs_replay_swap_attrs(lr_attr_t *lrattr) 25190075Sobrien{ 25290075Sobrien /* swap the lr_attr structure */ 25390075Sobrien byteswap_uint32_array(lrattr, sizeof (*lrattr)); 25490075Sobrien /* swap the bitmap */ 25590075Sobrien byteswap_uint32_array(lrattr + 1, (lrattr->lr_attr_masksize - 1) * 25690075Sobrien sizeof (uint32_t)); 25790075Sobrien /* swap the attributes, create time + 64 bit word for attributes */ 25890075Sobrien byteswap_uint64_array((caddr_t)(lrattr + 1) + (sizeof (uint32_t) * 25990075Sobrien (lrattr->lr_attr_masksize - 1)), 3 * sizeof (uint64_t)); 26090075Sobrien} 26190075Sobrien 26290075Sobrien/* 26390075Sobrien * Replay file create with optional ACL, xvattr information as well 26490075Sobrien * as option FUID information. 26590075Sobrien */ 26690075Sobrienstatic int 26790075Sobrienzfs_replay_create_acl(zfsvfs_t *zfsvfs, 268132718Skan lr_acl_create_t *lracl, boolean_t byteswap) 269169689Skan{ 270169689Skan char *name = NULL; /* location determined later */ 271132718Skan lr_create_t *lr = (lr_create_t *)lracl; 272132718Skan znode_t *dzp; 273132718Skan vnode_t *vp = NULL; 274169689Skan xvattr_t xva; 275169689Skan int vflg = 0; 276117395Skan vsecattr_t vsec = { 0 }; 277169689Skan lr_attr_t *lrattr; 278169689Skan void *aclstart; 279132718Skan void *fuidstart; 280169689Skan size_t xvatlen = 0; 281132718Skan uint64_t txtype; 282132718Skan int error; 28390075Sobrien 284132718Skan txtype = (lr->lr_common.lrc_txtype & ~TX_CI); 285132718Skan if (byteswap) { 286132718Skan byteswap_uint64_array(lracl, sizeof (*lracl)); 287132718Skan if (txtype == TX_CREATE_ACL_ATTR || 288132718Skan txtype == TX_MKDIR_ACL_ATTR) { 289132718Skan lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 290132718Skan zfs_replay_swap_attrs(lrattr); 291169689Skan xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 292132718Skan } 293169689Skan 294132718Skan aclstart = (caddr_t)(lracl + 1) + xvatlen; 295132718Skan zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); 296132718Skan /* swap fuids */ 29790075Sobrien if (lracl->lr_fuidcnt) { 29890075Sobrien byteswap_uint64_array((caddr_t)aclstart + 29990075Sobrien ZIL_ACE_LENGTH(lracl->lr_acl_bytes), 30090075Sobrien lracl->lr_fuidcnt * sizeof (uint64_t)); 30190075Sobrien } 30290075Sobrien } 30390075Sobrien 30490075Sobrien if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 30590075Sobrien return (error); 30690075Sobrien 30790075Sobrien xva_init(&xva); 30890075Sobrien zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 309169689Skan lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 31090075Sobrien 31190075Sobrien /* 312117395Skan * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 313169689Skan * eventually end up in zfs_mknode(), which assigns the object's 314169689Skan * creation time and generation number. The generic VOP_CREATE() 31590075Sobrien * doesn't have either concept, so we smuggle the values inside 31690075Sobrien * the vattr's otherwise unused va_ctime and va_nblocks fields. 31790075Sobrien */ 318117395Skan ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 319169689Skan xva.xva_vattr.va_nblocks = lr->lr_gen; 320169689Skan 321169689Skan error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 32290075Sobrien if (error != ENOENT) 32390075Sobrien goto bail; 324117395Skan 32590075Sobrien if (lr->lr_common.lrc_txtype & TX_CI) 326169689Skan vflg |= FIGNORECASE; 32790075Sobrien switch (txtype) { 32890075Sobrien case TX_CREATE_ACL: 32990075Sobrien aclstart = (caddr_t)(lracl + 1); 33090075Sobrien fuidstart = (caddr_t)aclstart + 331169689Skan ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 33290075Sobrien zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 33390075Sobrien (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 33490075Sobrien lr->lr_uid, lr->lr_gid); 335117395Skan /*FALLTHROUGH*/ 33690075Sobrien case TX_CREATE_ACL_ATTR: 33790075Sobrien if (name == NULL) { 338169689Skan lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 339169689Skan xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 34090075Sobrien xva.xva_vattr.va_mask |= AT_XVATTR; 34190075Sobrien zfs_replay_xvattr(lrattr, &xva); 34290075Sobrien } 34390075Sobrien vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 344169689Skan vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 345169689Skan vsec.vsa_aclcnt = lracl->lr_aclcnt; 34690075Sobrien vsec.vsa_aclentsz = lracl->lr_acl_bytes; 347169689Skan vsec.vsa_aclflags = lracl->lr_acl_flags; 34890075Sobrien if (zfsvfs->z_fuid_replay == NULL) { 349169689Skan fuidstart = (caddr_t)(lracl + 1) + xvatlen + 35090075Sobrien ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 35190075Sobrien zfsvfs->z_fuid_replay = 35290075Sobrien zfs_replay_fuids(fuidstart, 35390075Sobrien (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 35490075Sobrien lr->lr_uid, lr->lr_gid); 355117395Skan } 356169689Skan 35790075Sobrien#ifdef TODO 35890075Sobrien error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr, 35990075Sobrien 0, 0, &vp, kcred, vflg, NULL, &vsec); 360169689Skan#else 361169689Skan panic("%s:%u: unsupported condition", __func__, __LINE__); 362169689Skan#endif 36390075Sobrien break; 36490075Sobrien case TX_MKDIR_ACL: 36590075Sobrien aclstart = (caddr_t)(lracl + 1); 366169689Skan fuidstart = (caddr_t)aclstart + 36790075Sobrien ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 36890075Sobrien zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, 369169689Skan (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 370117395Skan lr->lr_uid, lr->lr_gid); 37190075Sobrien /*FALLTHROUGH*/ 37290075Sobrien case TX_MKDIR_ACL_ATTR: 37390075Sobrien if (name == NULL) { 37490075Sobrien lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); 37590075Sobrien xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 37690075Sobrien zfs_replay_xvattr(lrattr, &xva); 37790075Sobrien } 37890075Sobrien vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; 37990075Sobrien vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; 38090075Sobrien vsec.vsa_aclcnt = lracl->lr_aclcnt; 38190075Sobrien vsec.vsa_aclentsz = lracl->lr_acl_bytes; 38290075Sobrien vsec.vsa_aclflags = lracl->lr_acl_flags; 38390075Sobrien if (zfsvfs->z_fuid_replay == NULL) { 38490075Sobrien fuidstart = (caddr_t)(lracl + 1) + xvatlen + 38590075Sobrien ZIL_ACE_LENGTH(lracl->lr_acl_bytes); 386117395Skan zfsvfs->z_fuid_replay = 38790075Sobrien zfs_replay_fuids(fuidstart, 38890075Sobrien (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, 38990075Sobrien lr->lr_uid, lr->lr_gid); 39090075Sobrien } 39190075Sobrien#ifdef TODO 39290075Sobrien error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr, 393169689Skan &vp, kcred, NULL, vflg, &vsec); 39490075Sobrien#else 39590075Sobrien panic("%s:%u: unsupported condition", __func__, __LINE__); 39690075Sobrien#endif 39790075Sobrien break; 39890075Sobrien default: 39990075Sobrien error = ENOTSUP; 400169689Skan } 40190075Sobrien 40290075Sobrienbail: 40390075Sobrien if (error == 0 && vp != NULL) 40490075Sobrien VN_RELE(vp); 40590075Sobrien 40690075Sobrien VN_RELE(ZTOV(dzp)); 40790075Sobrien 40890075Sobrien if (zfsvfs->z_fuid_replay) 40990075Sobrien zfs_fuid_info_free(zfsvfs->z_fuid_replay); 41090075Sobrien zfsvfs->z_fuid_replay = NULL; 41190075Sobrien 41290075Sobrien return (error); 41390075Sobrien} 41490075Sobrien 41590075Sobrienstatic int 41690075Sobrienzfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap) 41790075Sobrien{ 41890075Sobrien char *name = NULL; /* location determined later */ 419169689Skan char *link; /* symlink content follows name */ 420169689Skan znode_t *dzp; 421169689Skan vnode_t *vp = NULL; 422169689Skan xvattr_t xva; 423169689Skan int vflg = 0; 424169689Skan size_t lrsize = sizeof (lr_create_t); 425169689Skan lr_attr_t *lrattr; 426169689Skan void *start; 427169689Skan size_t xvatlen; 428169689Skan uint64_t txtype; 429169689Skan struct componentname cn; 430169689Skan int error; 43190075Sobrien 43290075Sobrien txtype = (lr->lr_common.lrc_txtype & ~TX_CI); 43390075Sobrien if (byteswap) { 43490075Sobrien byteswap_uint64_array(lr, sizeof (*lr)); 43590075Sobrien if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) 43690075Sobrien zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 43790075Sobrien } 43890075Sobrien 43990075Sobrien 44090075Sobrien if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 44190075Sobrien return (error); 44290075Sobrien 44390075Sobrien xva_init(&xva); 444169689Skan zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID, 44590075Sobrien lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); 44690075Sobrien 44790075Sobrien /* 44890075Sobrien * All forms of zfs create (create, mkdir, mkxattrdir, symlink) 44990075Sobrien * eventually end up in zfs_mknode(), which assigns the object's 45090075Sobrien * creation time and generation number. The generic VOP_CREATE() 45190075Sobrien * doesn't have either concept, so we smuggle the values inside 45290075Sobrien * the vattr's otherwise unused va_ctime and va_nblocks fields. 45390075Sobrien */ 45490075Sobrien ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); 45590075Sobrien xva.xva_vattr.va_nblocks = lr->lr_gen; 45690075Sobrien 45790075Sobrien error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL); 45890075Sobrien if (error != ENOENT) 45990075Sobrien goto out; 46090075Sobrien 46190075Sobrien if (lr->lr_common.lrc_txtype & TX_CI) 46290075Sobrien vflg |= FIGNORECASE; 46390075Sobrien 46490075Sobrien /* 46590075Sobrien * Symlinks don't have fuid info, and CIFS never creates 46690075Sobrien * symlinks. 46790075Sobrien * 46890075Sobrien * The _ATTR versions will grab the fuid info in their subcases. 46990075Sobrien */ 47090075Sobrien if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK && 47190075Sobrien (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR && 47290075Sobrien (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) { 47390075Sobrien start = (lr + 1); 47490075Sobrien zfsvfs->z_fuid_replay = 47590075Sobrien zfs_replay_fuid_domain(start, &start, 47690075Sobrien lr->lr_uid, lr->lr_gid); 47790075Sobrien } 47890075Sobrien 47990075Sobrien cn.cn_cred = kcred; 48090075Sobrien cn.cn_thread = curthread; 481169689Skan cn.cn_flags = SAVENAME; 48290075Sobrien 483169689Skan vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); 484117395Skan switch (txtype) { 48590075Sobrien case TX_CREATE_ATTR: 48690075Sobrien lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 487117395Skan xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 48890075Sobrien zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 48990075Sobrien start = (caddr_t)(lr + 1) + xvatlen; 49090075Sobrien zfsvfs->z_fuid_replay = 49190075Sobrien zfs_replay_fuid_domain(start, &start, 49290075Sobrien lr->lr_uid, lr->lr_gid); 49390075Sobrien name = (char *)start; 494169689Skan 495169689Skan /*FALLTHROUGH*/ 496169689Skan case TX_CREATE: 497169689Skan if (name == NULL) 498169689Skan name = (char *)start; 49990075Sobrien 50090075Sobrien cn.cn_nameptr = name; 50190075Sobrien error = VOP_CREATE(ZTOV(dzp), &vp, &cn, &xva.xva_vattr /*,vflg*/); 50290075Sobrien break; 50390075Sobrien case TX_MKDIR_ATTR: 50490075Sobrien lrattr = (lr_attr_t *)(caddr_t)(lr + 1); 50590075Sobrien xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); 50690075Sobrien zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); 50790075Sobrien start = (caddr_t)(lr + 1) + xvatlen; 50890075Sobrien zfsvfs->z_fuid_replay = 50990075Sobrien zfs_replay_fuid_domain(start, &start, 51090075Sobrien lr->lr_uid, lr->lr_gid); 51190075Sobrien name = (char *)start; 51290075Sobrien 51390075Sobrien /*FALLTHROUGH*/ 51490075Sobrien case TX_MKDIR: 51590075Sobrien if (name == NULL) 516117395Skan name = (char *)(lr + 1); 51790075Sobrien 51890075Sobrien cn.cn_nameptr = name; 51990075Sobrien error = VOP_MKDIR(ZTOV(dzp), &vp, &cn, &xva.xva_vattr /*,vflg*/); 52090075Sobrien break; 521169689Skan case TX_MKXATTR: 52290075Sobrien error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &vp, kcred); 52390075Sobrien break; 52490075Sobrien case TX_SYMLINK: 52590075Sobrien name = (char *)(lr + 1); 52690075Sobrien link = name + strlen(name) + 1; 52790075Sobrien cn.cn_nameptr = name; 528169689Skan error = VOP_SYMLINK(ZTOV(dzp), &vp, &cn, &xva.xva_vattr, link /*,vflg*/); 52990075Sobrien break; 530169689Skan default: 53190075Sobrien error = ENOTSUP; 532169689Skan } 53390075Sobrien VOP_UNLOCK(ZTOV(dzp), 0); 53490075Sobrien 53590075Sobrienout: 53690075Sobrien if (error == 0 && vp != NULL) 53790075Sobrien VN_URELE(vp); 53890075Sobrien 53990075Sobrien VN_RELE(ZTOV(dzp)); 54090075Sobrien 54190075Sobrien if (zfsvfs->z_fuid_replay) 54290075Sobrien zfs_fuid_info_free(zfsvfs->z_fuid_replay); 54390075Sobrien zfsvfs->z_fuid_replay = NULL; 54490075Sobrien return (error); 54590075Sobrien} 54690075Sobrien 54790075Sobrienstatic int 548169689Skanzfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap) 549169689Skan{ 550169689Skan char *name = (char *)(lr + 1); /* name follows lr_remove_t */ 551169689Skan znode_t *dzp; 55290075Sobrien struct componentname cn; 55390075Sobrien vnode_t *vp; 55490075Sobrien int error; 555169689Skan int vflg = 0; 556169689Skan 55790075Sobrien if (byteswap) 55890075Sobrien byteswap_uint64_array(lr, sizeof (*lr)); 559169689Skan 560169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 56190075Sobrien return (error); 56290075Sobrien 56390075Sobrien if (lr->lr_common.lrc_txtype & TX_CI) 56490075Sobrien vflg |= FIGNORECASE; 56590075Sobrien cn.cn_nameptr = name; 56690075Sobrien cn.cn_namelen = strlen(name); 56790075Sobrien cn.cn_nameiop = DELETE; 56890075Sobrien cn.cn_flags = ISLASTCN | SAVENAME; 56990075Sobrien cn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 57090075Sobrien cn.cn_cred = kcred; 57190075Sobrien cn.cn_thread = curthread; 57290075Sobrien vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); 57390075Sobrien error = VOP_LOOKUP(ZTOV(dzp), &vp, &cn); 57490075Sobrien if (error != 0) { 57590075Sobrien VOP_UNLOCK(ZTOV(dzp), 0); 57690075Sobrien goto fail; 57790075Sobrien } 57890075Sobrien 579169689Skan switch ((int)lr->lr_common.lrc_txtype) { 580169689Skan case TX_REMOVE: 581169689Skan error = VOP_REMOVE(ZTOV(dzp), vp, &cn /*,vflg*/); 582169689Skan break; 583169689Skan case TX_RMDIR: 584169689Skan error = VOP_RMDIR(ZTOV(dzp), vp, &cn /*,vflg*/); 585169689Skan break; 586169689Skan default: 587169689Skan error = ENOTSUP; 588169689Skan } 589169689Skan vput(vp); 590169689Skan VOP_UNLOCK(ZTOV(dzp), 0); 591169689Skan 592169689Skanfail: 59390075Sobrien VN_RELE(ZTOV(dzp)); 59490075Sobrien 59590075Sobrien return (error); 59690075Sobrien} 59790075Sobrien 59890075Sobrienstatic int 599169689Skanzfs_replay_link(zfsvfs_t *zfsvfs, lr_link_t *lr, boolean_t byteswap) 600169689Skan{ 601169689Skan char *name = (char *)(lr + 1); /* name follows lr_link_t */ 602169689Skan znode_t *dzp, *zp; 603169689Skan struct componentname cn; 60490075Sobrien int error; 60590075Sobrien int vflg = 0; 60690075Sobrien 60790075Sobrien if (byteswap) 60890075Sobrien byteswap_uint64_array(lr, sizeof (*lr)); 60990075Sobrien 610169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) 611169689Skan return (error); 612169689Skan 613169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_link_obj, &zp)) != 0) { 614169689Skan VN_RELE(ZTOV(dzp)); 615169689Skan return (error); 616169689Skan } 617169689Skan 618169689Skan if (lr->lr_common.lrc_txtype & TX_CI) 619169689Skan vflg |= FIGNORECASE; 620169689Skan 62190075Sobrien cn.cn_nameptr = name; 62290075Sobrien cn.cn_cred = kcred; 62390075Sobrien cn.cn_thread = curthread; 62490075Sobrien cn.cn_flags = SAVENAME; 62590075Sobrien 62690075Sobrien vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY); 62790075Sobrien vn_lock(ZTOV(zp), LK_EXCLUSIVE | LK_RETRY); 62890075Sobrien error = VOP_LINK(ZTOV(dzp), ZTOV(zp), &cn /*,vflg*/); 62990075Sobrien VOP_UNLOCK(ZTOV(zp), 0); 63090075Sobrien VOP_UNLOCK(ZTOV(dzp), 0); 63190075Sobrien 63290075Sobrien VN_RELE(ZTOV(zp)); 63390075Sobrien VN_RELE(ZTOV(dzp)); 63490075Sobrien 63590075Sobrien return (error); 636169689Skan} 637169689Skan 638169689Skanstatic int 639169689Skanzfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap) 64090075Sobrien{ 64190075Sobrien char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ 64290075Sobrien char *tname = sname + strlen(sname) + 1; 64390075Sobrien znode_t *sdzp, *tdzp; 64490075Sobrien struct componentname scn, tcn; 64590075Sobrien vnode_t *svp, *tvp; 64690075Sobrien kthread_t *td = curthread; 64790075Sobrien int error; 64890075Sobrien int vflg = 0; 64990075Sobrien 650117395Skan if (byteswap) 651169689Skan byteswap_uint64_array(lr, sizeof (*lr)); 652169689Skan 653169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) 654169689Skan return (error); 655169689Skan 656169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { 657169689Skan VN_RELE(ZTOV(sdzp)); 658169689Skan return (error); 65990075Sobrien } 660169689Skan 661169689Skan if (lr->lr_common.lrc_txtype & TX_CI) 662169689Skan vflg |= FIGNORECASE; 663169689Skan svp = tvp = NULL; 664169689Skan 665169689Skan scn.cn_nameptr = sname; 666169689Skan scn.cn_namelen = strlen(sname); 667169689Skan scn.cn_nameiop = DELETE; 668169689Skan scn.cn_flags = ISLASTCN | SAVENAME; 669169689Skan scn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 670169689Skan scn.cn_cred = kcred; 671169689Skan scn.cn_thread = td; 672169689Skan vn_lock(ZTOV(sdzp), LK_EXCLUSIVE | LK_RETRY); 673169689Skan error = VOP_LOOKUP(ZTOV(sdzp), &svp, &scn); 674169689Skan VOP_UNLOCK(ZTOV(sdzp), 0); 675169689Skan if (error != 0) 676169689Skan goto fail; 677169689Skan VOP_UNLOCK(svp, 0); 678169689Skan 679169689Skan tcn.cn_nameptr = tname; 680169689Skan tcn.cn_namelen = strlen(tname); 681169689Skan tcn.cn_nameiop = RENAME; 68290075Sobrien tcn.cn_flags = ISLASTCN | SAVENAME; 68390075Sobrien tcn.cn_lkflags = LK_EXCLUSIVE | LK_RETRY; 68490075Sobrien tcn.cn_cred = kcred; 68590075Sobrien tcn.cn_thread = td; 68690075Sobrien vn_lock(ZTOV(tdzp), LK_EXCLUSIVE | LK_RETRY); 68790075Sobrien error = VOP_LOOKUP(ZTOV(tdzp), &tvp, &tcn); 68890075Sobrien if (error == EJUSTRETURN) 68990075Sobrien tvp = NULL; 690117395Skan else if (error != 0) { 69190075Sobrien VOP_UNLOCK(ZTOV(tdzp), 0); 69290075Sobrien goto fail; 69390075Sobrien } 69490075Sobrien 695117395Skan error = VOP_RENAME(ZTOV(sdzp), svp, &scn, ZTOV(tdzp), tvp, &tcn /*,vflg*/); 69690075Sobrien return (error); 69790075Sobrienfail: 698132718Skan if (svp != NULL) 69990075Sobrien vrele(svp); 70090075Sobrien if (tvp != NULL) 70190075Sobrien vrele(tvp); 70290075Sobrien VN_RELE(ZTOV(tdzp)); 70390075Sobrien VN_RELE(ZTOV(sdzp)); 70490075Sobrien 70590075Sobrien return (error); 706132718Skan} 70790075Sobrien 70890075Sobrienstatic int 70990075Sobrienzfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 71090075Sobrien{ 71190075Sobrien char *data = (char *)(lr + 1); /* data follows lr_write_t */ 71290075Sobrien znode_t *zp; 71390075Sobrien int error; 71490075Sobrien ssize_t resid; 71590075Sobrien uint64_t eod, offset, length; 71690075Sobrien 71790075Sobrien if (byteswap) 71890075Sobrien byteswap_uint64_array(lr, sizeof (*lr)); 71990075Sobrien 72090075Sobrien if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { 721117395Skan /* 72290075Sobrien * As we can log writes out of order, it's possible the 72390075Sobrien * file has been removed. In this case just drop the write 72490075Sobrien * and return success. 72590075Sobrien */ 72690075Sobrien if (error == ENOENT) 72790075Sobrien error = 0; 72890075Sobrien return (error); 72990075Sobrien } 73090075Sobrien 73190075Sobrien offset = lr->lr_offset; 73290075Sobrien length = lr->lr_length; 73390075Sobrien eod = offset + length; /* end of data for this write */ 73490075Sobrien 73590075Sobrien /* 73690075Sobrien * This may be a write from a dmu_sync() for a whole block, 73790075Sobrien * and may extend beyond the current end of the file. 73890075Sobrien * We can't just replay what was written for this TX_WRITE as 739169689Skan * a future TX_WRITE2 may extend the eof and the data for that 74090075Sobrien * write needs to be there. So we write the whole block and 74190075Sobrien * reduce the eof. This needs to be done within the single dmu 742169689Skan * transaction created within vn_rdwr -> zfs_write. So a possible 74390075Sobrien * new end of file is passed through in zfsvfs->z_replay_eof 74490075Sobrien */ 745169689Skan 746169689Skan zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */ 747169689Skan 748169689Skan /* If it's a dmu_sync() block, write the whole block */ 749169689Skan if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { 750169689Skan uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr); 751169689Skan if (length < blocksize) { 752169689Skan offset -= offset % blocksize; 753169689Skan length = blocksize; 754169689Skan } 755169689Skan if (zp->z_size < eod) 756169689Skan zfsvfs->z_replay_eof = eod; 757169689Skan } 758169689Skan 75990075Sobrien error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset, 76090075Sobrien UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); 761169689Skan 762169689Skan VN_RELE(ZTOV(zp)); 763169689Skan zfsvfs->z_replay_eof = 0; /* safety */ 764169689Skan 765169689Skan return (error); 76690075Sobrien} 76790075Sobrien 76890075Sobrien/* 76990075Sobrien * TX_WRITE2 are only generated when dmu_sync() returns EALREADY 77090075Sobrien * meaning the pool block is already being synced. So now that we always write 77190075Sobrien * out full blocks, all we have to do is expand the eof if 77290075Sobrien * the file is grown. 77390075Sobrien */ 77490075Sobrienstatic int 77590075Sobrienzfs_replay_write2(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap) 77690075Sobrien{ 77790075Sobrien znode_t *zp; 77890075Sobrien int error; 779169689Skan uint64_t end; 780169689Skan 781169689Skan if (byteswap) 782169689Skan byteswap_uint64_array(lr, sizeof (*lr)); 783169689Skan 784169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 785169689Skan return (error); 786169689Skan 787169689Skantop: 788169689Skan end = lr->lr_offset + lr->lr_length; 78990075Sobrien if (end > zp->z_size) { 79090075Sobrien dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); 79190075Sobrien 792169689Skan zp->z_size = end; 793169689Skan dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); 794169689Skan error = dmu_tx_assign(tx, TXG_WAIT); 795169689Skan if (error) { 796169689Skan VN_RELE(ZTOV(zp)); 797169689Skan if (error == ERESTART) { 798169689Skan dmu_tx_wait(tx); 799169689Skan dmu_tx_abort(tx); 800169689Skan goto top; 801169689Skan } 802169689Skan dmu_tx_abort(tx); 803169689Skan return (error); 804169689Skan } 805169689Skan (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), 806169689Skan (void *)&zp->z_size, sizeof (uint64_t), tx); 807169689Skan 808169689Skan /* Ensure the replayed seq is updated */ 809169689Skan (void) zil_replaying(zfsvfs->z_log, tx); 810169689Skan 811169689Skan dmu_tx_commit(tx); 812169689Skan } 813169689Skan 814169689Skan VN_RELE(ZTOV(zp)); 815169689Skan 816169689Skan return (error); 817169689Skan} 818169689Skan 819169689Skanstatic int 820169689Skanzfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap) 821169689Skan{ 822169689Skan#ifdef sun 823169689Skan znode_t *zp; 824169689Skan flock64_t fl; 825169689Skan int error; 826169689Skan 827169689Skan if (byteswap) 828169689Skan byteswap_uint64_array(lr, sizeof (*lr)); 829169689Skan 830169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 831169689Skan return (error); 832169689Skan 833169689Skan bzero(&fl, sizeof (fl)); 834169689Skan fl.l_type = F_WRLCK; 835169689Skan fl.l_whence = 0; 836169689Skan fl.l_start = lr->lr_offset; 837169689Skan fl.l_len = lr->lr_length; 838169689Skan 839169689Skan error = VOP_SPACE(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX, 840169689Skan lr->lr_offset, kcred, NULL); 841169689Skan 842169689Skan VN_RELE(ZTOV(zp)); 843169689Skan 844169689Skan return (error); 845169689Skan#else /* !sun */ 846169689Skan ZFS_LOG(0, "Unexpected code path, report to pjd@FreeBSD.org"); 847169689Skan return (EOPNOTSUPP); 848169689Skan#endif /* !sun */ 849169689Skan} 850169689Skan 851169689Skanstatic int 852169689Skanzfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap) 853169689Skan{ 854169689Skan znode_t *zp; 855169689Skan xvattr_t xva; 856169689Skan vattr_t *vap = &xva.xva_vattr; 857169689Skan vnode_t *vp; 858169689Skan int error; 859169689Skan void *start; 860169689Skan 861169689Skan xva_init(&xva); 862169689Skan if (byteswap) { 863169689Skan byteswap_uint64_array(lr, sizeof (*lr)); 864169689Skan 865169689Skan if ((lr->lr_mask & AT_XVATTR) && 866169689Skan zfsvfs->z_version >= ZPL_VERSION_INITIAL) 867169689Skan zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); 868169689Skan } 869169689Skan 870169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 871169689Skan return (error); 872169689Skan 87390075Sobrien zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, 87490075Sobrien lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); 87590075Sobrien 87690075Sobrien vap->va_size = lr->lr_size; 87790075Sobrien ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); 87890075Sobrien ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); 879132718Skan 88090075Sobrien /* 881169689Skan * Fill in xvattr_t portions if necessary. 882169689Skan */ 88390075Sobrien 884117395Skan start = (lr_setattr_t *)(lr + 1); 885169689Skan if (vap->va_mask & AT_XVATTR) { 88690075Sobrien zfs_replay_xvattr((lr_attr_t *)start, &xva); 887117395Skan start = (caddr_t)start + 888169689Skan ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); 889169689Skan } else 890169689Skan xva.xva_vattr.va_mask &= ~AT_XVATTR; 89190075Sobrien 892169689Skan zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, 89390075Sobrien lr->lr_uid, lr->lr_gid); 894169689Skan 89590075Sobrien vp = ZTOV(zp); 896169689Skan vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 89790075Sobrien error = VOP_SETATTR(vp, vap, kcred); 898169689Skan VOP_UNLOCK(vp, 0); 899117395Skan 90090075Sobrien zfs_fuid_info_free(zfsvfs->z_fuid_replay); 90190075Sobrien zfsvfs->z_fuid_replay = NULL; 90290075Sobrien VN_RELE(vp); 903169689Skan 904169689Skan return (error); 90590075Sobrien} 90690075Sobrien 907132718Skanstatic int 90890075Sobrienzfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap) 909169689Skan{ 910169689Skan ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */ 911169689Skan vsecattr_t vsa; 912169689Skan znode_t *zp; 913169689Skan int error; 914169689Skan 915169689Skan if (byteswap) { 916169689Skan byteswap_uint64_array(lr, sizeof (*lr)); 917169689Skan zfs_oldace_byteswap(ace, lr->lr_aclcnt); 918169689Skan } 919169689Skan 920169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 921169689Skan return (error); 922169689Skan 923169689Skan bzero(&vsa, sizeof (vsa)); 924169689Skan vsa.vsa_mask = VSA_ACE | VSA_ACECNT; 92590075Sobrien vsa.vsa_aclcnt = lr->lr_aclcnt; 92690075Sobrien vsa.vsa_aclentsz = sizeof (ace_t) * vsa.vsa_aclcnt; 927169689Skan vsa.vsa_aclflags = 0; 928169689Skan vsa.vsa_aclentp = ace; 929169689Skan 930169689Skan#ifdef TODO 931169689Skan error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); 932169689Skan#else 933169689Skan panic("%s:%u: unsupported condition", __func__, __LINE__); 934169689Skan#endif 935169689Skan 93690075Sobrien VN_RELE(ZTOV(zp)); 93790075Sobrien 93890075Sobrien return (error); 939132718Skan} 94090075Sobrien 941169689Skan/* 942169689Skan * Replaying ACLs is complicated by FUID support. 94390075Sobrien * The log record may contain some optional data 94490075Sobrien * to be used for replaying FUID's. These pieces 94590075Sobrien * are the actual FUIDs that were created initially. 94690075Sobrien * The FUID table index may no longer be valid and 94790075Sobrien * during zfs_create() a new index may be assigned. 94890075Sobrien * Because of this the log will contain the original 949132718Skan * doman+rid in order to create a new FUID. 95090075Sobrien * 95190075Sobrien * The individual ACEs may contain an ephemeral uid/gid which is no 95290075Sobrien * longer valid and will need to be replaced with an actual FUID. 95390075Sobrien * 954169689Skan */ 955169689Skanstatic int 956169689Skanzfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap) 957169689Skan{ 958169689Skan ace_t *ace = (ace_t *)(lr + 1); 959169689Skan vsecattr_t vsa; 960169689Skan znode_t *zp; 961169689Skan int error; 962169689Skan 963169689Skan if (byteswap) { 964169689Skan byteswap_uint64_array(lr, sizeof (*lr)); 965169689Skan zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE); 966169689Skan if (lr->lr_fuidcnt) { 967169689Skan byteswap_uint64_array((caddr_t)ace + 968169689Skan ZIL_ACE_LENGTH(lr->lr_acl_bytes), 969169689Skan lr->lr_fuidcnt * sizeof (uint64_t)); 970169689Skan } 971169689Skan } 972169689Skan 973169689Skan if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) 974169689Skan return (error); 975169689Skan 976169689Skan#ifdef TODO 977169689Skan bzero(&vsa, sizeof (vsa)); 978169689Skan vsa.vsa_mask = VSA_ACE | VSA_ACECNT | VSA_ACE_ACLFLAGS; 979169689Skan vsa.vsa_aclcnt = lr->lr_aclcnt; 980169689Skan vsa.vsa_aclentp = ace; 981169689Skan vsa.vsa_aclentsz = lr->lr_acl_bytes; 982169689Skan vsa.vsa_aclflags = lr->lr_acl_flags; 983169689Skan 984117395Skan if (lr->lr_fuidcnt) { 98590075Sobrien void *fuidstart = (caddr_t)ace + 98690075Sobrien ZIL_ACE_LENGTH(lr->lr_acl_bytes); 987169689Skan 988169689Skan zfsvfs->z_fuid_replay = 98990075Sobrien zfs_replay_fuids(fuidstart, &fuidstart, 99090075Sobrien lr->lr_fuidcnt, lr->lr_domcnt, 0, 0); 991169689Skan } 992169689Skan 993169689Skan error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL); 994169689Skan 995169689Skan if (zfsvfs->z_fuid_replay) 996117395Skan zfs_fuid_info_free(zfsvfs->z_fuid_replay); 997169689Skan#else 998169689Skan error = EOPNOTSUPP; 999169689Skan#endif 1000117395Skan 1001169689Skan zfsvfs->z_fuid_replay = NULL; 1002169689Skan VN_RELE(ZTOV(zp)); 1003117395Skan 1004169689Skan return (error); 1005169689Skan} 1006169689Skan 1007169689Skan/* 1008169689Skan * Callback vectors for replaying records 1009117395Skan */ 1010169689Skanzil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE] = { 1011169689Skan zfs_replay_error, /* 0 no such transaction type */ 1012169689Skan zfs_replay_create, /* TX_CREATE */ 1013169689Skan zfs_replay_create, /* TX_MKDIR */ 1014169689Skan zfs_replay_create, /* TX_MKXATTR */ 1015169689Skan zfs_replay_create, /* TX_SYMLINK */ 1016169689Skan zfs_replay_remove, /* TX_REMOVE */ 1017169689Skan zfs_replay_remove, /* TX_RMDIR */ 1018169689Skan zfs_replay_link, /* TX_LINK */ 1019169689Skan zfs_replay_rename, /* TX_RENAME */ 1020169689Skan zfs_replay_write, /* TX_WRITE */ 1021169689Skan zfs_replay_truncate, /* TX_TRUNCATE */ 1022169689Skan zfs_replay_setattr, /* TX_SETATTR */ 102390075Sobrien zfs_replay_acl_v0, /* TX_ACL_V0 */ 1024169689Skan zfs_replay_acl, /* TX_ACL */ 1025169689Skan zfs_replay_create_acl, /* TX_CREATE_ACL */ 1026169689Skan zfs_replay_create, /* TX_CREATE_ATTR */ 1027169689Skan zfs_replay_create_acl, /* TX_CREATE_ACL_ATTR */ 1028169689Skan zfs_replay_create_acl, /* TX_MKDIR_ACL */ 1029117395Skan zfs_replay_create, /* TX_MKDIR_ATTR */ 1030169689Skan zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */ 1031169689Skan zfs_replay_write2, /* TX_WRITE2 */ 1032117395Skan}; 1033169689Skan