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