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