xref: /freebsd/sys/contrib/openzfs/module/zfs/zfs_log.c (revision eda14cbc264d6969b02f2b1994cef11148e914f1)
1*eda14cbcSMatt Macy /*
2*eda14cbcSMatt Macy  * CDDL HEADER START
3*eda14cbcSMatt Macy  *
4*eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5*eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6*eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7*eda14cbcSMatt Macy  *
8*eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*eda14cbcSMatt Macy  * or http://www.opensolaris.org/os/licensing.
10*eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11*eda14cbcSMatt Macy  * and limitations under the License.
12*eda14cbcSMatt Macy  *
13*eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14*eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16*eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17*eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18*eda14cbcSMatt Macy  *
19*eda14cbcSMatt Macy  * CDDL HEADER END
20*eda14cbcSMatt Macy  */
21*eda14cbcSMatt Macy /*
22*eda14cbcSMatt Macy  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23*eda14cbcSMatt Macy  * Copyright (c) 2015, 2018 by Delphix. All rights reserved.
24*eda14cbcSMatt Macy  */
25*eda14cbcSMatt Macy 
26*eda14cbcSMatt Macy 
27*eda14cbcSMatt Macy #include <sys/types.h>
28*eda14cbcSMatt Macy #include <sys/param.h>
29*eda14cbcSMatt Macy #include <sys/sysmacros.h>
30*eda14cbcSMatt Macy #include <sys/cmn_err.h>
31*eda14cbcSMatt Macy #include <sys/kmem.h>
32*eda14cbcSMatt Macy #include <sys/thread.h>
33*eda14cbcSMatt Macy #include <sys/file.h>
34*eda14cbcSMatt Macy #include <sys/vfs.h>
35*eda14cbcSMatt Macy #include <sys/zfs_znode.h>
36*eda14cbcSMatt Macy #include <sys/zfs_dir.h>
37*eda14cbcSMatt Macy #include <sys/zil.h>
38*eda14cbcSMatt Macy #include <sys/zil_impl.h>
39*eda14cbcSMatt Macy #include <sys/byteorder.h>
40*eda14cbcSMatt Macy #include <sys/policy.h>
41*eda14cbcSMatt Macy #include <sys/stat.h>
42*eda14cbcSMatt Macy #include <sys/acl.h>
43*eda14cbcSMatt Macy #include <sys/dmu.h>
44*eda14cbcSMatt Macy #include <sys/dbuf.h>
45*eda14cbcSMatt Macy #include <sys/spa.h>
46*eda14cbcSMatt Macy #include <sys/zfs_fuid.h>
47*eda14cbcSMatt Macy #include <sys/dsl_dataset.h>
48*eda14cbcSMatt Macy 
49*eda14cbcSMatt Macy /*
50*eda14cbcSMatt Macy  * These zfs_log_* functions must be called within a dmu tx, in one
51*eda14cbcSMatt Macy  * of 2 contexts depending on zilog->z_replay:
52*eda14cbcSMatt Macy  *
53*eda14cbcSMatt Macy  * Non replay mode
54*eda14cbcSMatt Macy  * ---------------
55*eda14cbcSMatt Macy  * We need to record the transaction so that if it is committed to
56*eda14cbcSMatt Macy  * the Intent Log then it can be replayed.  An intent log transaction
57*eda14cbcSMatt Macy  * structure (itx_t) is allocated and all the information necessary to
58*eda14cbcSMatt Macy  * possibly replay the transaction is saved in it. The itx is then assigned
59*eda14cbcSMatt Macy  * a sequence number and inserted in the in-memory list anchored in the zilog.
60*eda14cbcSMatt Macy  *
61*eda14cbcSMatt Macy  * Replay mode
62*eda14cbcSMatt Macy  * -----------
63*eda14cbcSMatt Macy  * We need to mark the intent log record as replayed in the log header.
64*eda14cbcSMatt Macy  * This is done in the same transaction as the replay so that they
65*eda14cbcSMatt Macy  * commit atomically.
66*eda14cbcSMatt Macy  */
67*eda14cbcSMatt Macy 
68*eda14cbcSMatt Macy int
69*eda14cbcSMatt Macy zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap)
70*eda14cbcSMatt Macy {
71*eda14cbcSMatt Macy 	int isxvattr = (vap->va_mask & ATTR_XVATTR);
72*eda14cbcSMatt Macy 	switch (type) {
73*eda14cbcSMatt Macy 	case Z_FILE:
74*eda14cbcSMatt Macy 		if (vsecp == NULL && !isxvattr)
75*eda14cbcSMatt Macy 			return (TX_CREATE);
76*eda14cbcSMatt Macy 		if (vsecp && isxvattr)
77*eda14cbcSMatt Macy 			return (TX_CREATE_ACL_ATTR);
78*eda14cbcSMatt Macy 		if (vsecp)
79*eda14cbcSMatt Macy 			return (TX_CREATE_ACL);
80*eda14cbcSMatt Macy 		else
81*eda14cbcSMatt Macy 			return (TX_CREATE_ATTR);
82*eda14cbcSMatt Macy 		/*NOTREACHED*/
83*eda14cbcSMatt Macy 	case Z_DIR:
84*eda14cbcSMatt Macy 		if (vsecp == NULL && !isxvattr)
85*eda14cbcSMatt Macy 			return (TX_MKDIR);
86*eda14cbcSMatt Macy 		if (vsecp && isxvattr)
87*eda14cbcSMatt Macy 			return (TX_MKDIR_ACL_ATTR);
88*eda14cbcSMatt Macy 		if (vsecp)
89*eda14cbcSMatt Macy 			return (TX_MKDIR_ACL);
90*eda14cbcSMatt Macy 		else
91*eda14cbcSMatt Macy 			return (TX_MKDIR_ATTR);
92*eda14cbcSMatt Macy 	case Z_XATTRDIR:
93*eda14cbcSMatt Macy 		return (TX_MKXATTR);
94*eda14cbcSMatt Macy 	}
95*eda14cbcSMatt Macy 	ASSERT(0);
96*eda14cbcSMatt Macy 	return (TX_MAX_TYPE);
97*eda14cbcSMatt Macy }
98*eda14cbcSMatt Macy 
99*eda14cbcSMatt Macy /*
100*eda14cbcSMatt Macy  * build up the log data necessary for logging xvattr_t
101*eda14cbcSMatt Macy  * First lr_attr_t is initialized.  following the lr_attr_t
102*eda14cbcSMatt Macy  * is the mapsize and attribute bitmap copied from the xvattr_t.
103*eda14cbcSMatt Macy  * Following the bitmap and bitmapsize two 64 bit words are reserved
104*eda14cbcSMatt Macy  * for the create time which may be set.  Following the create time
105*eda14cbcSMatt Macy  * records a single 64 bit integer which has the bits to set on
106*eda14cbcSMatt Macy  * replay for the xvattr.
107*eda14cbcSMatt Macy  */
108*eda14cbcSMatt Macy static void
109*eda14cbcSMatt Macy zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
110*eda14cbcSMatt Macy {
111*eda14cbcSMatt Macy 	uint32_t	*bitmap;
112*eda14cbcSMatt Macy 	uint64_t	*attrs;
113*eda14cbcSMatt Macy 	uint64_t	*crtime;
114*eda14cbcSMatt Macy 	xoptattr_t	*xoap;
115*eda14cbcSMatt Macy 	void		*scanstamp;
116*eda14cbcSMatt Macy 	int		i;
117*eda14cbcSMatt Macy 
118*eda14cbcSMatt Macy 	xoap = xva_getxoptattr(xvap);
119*eda14cbcSMatt Macy 	ASSERT(xoap);
120*eda14cbcSMatt Macy 
121*eda14cbcSMatt Macy 	lrattr->lr_attr_masksize = xvap->xva_mapsize;
122*eda14cbcSMatt Macy 	bitmap = &lrattr->lr_attr_bitmap;
123*eda14cbcSMatt Macy 	for (i = 0; i != xvap->xva_mapsize; i++, bitmap++) {
124*eda14cbcSMatt Macy 		*bitmap = xvap->xva_reqattrmap[i];
125*eda14cbcSMatt Macy 	}
126*eda14cbcSMatt Macy 
127*eda14cbcSMatt Macy 	/* Now pack the attributes up in a single uint64_t */
128*eda14cbcSMatt Macy 	attrs = (uint64_t *)bitmap;
129*eda14cbcSMatt Macy 	crtime = attrs + 1;
130*eda14cbcSMatt Macy 	scanstamp = (caddr_t)(crtime + 2);
131*eda14cbcSMatt Macy 	*attrs = 0;
132*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_READONLY))
133*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_readonly == 0) ? 0 :
134*eda14cbcSMatt Macy 		    XAT0_READONLY;
135*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_HIDDEN))
136*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_hidden == 0) ? 0 :
137*eda14cbcSMatt Macy 		    XAT0_HIDDEN;
138*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_SYSTEM))
139*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_system == 0) ? 0 :
140*eda14cbcSMatt Macy 		    XAT0_SYSTEM;
141*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE))
142*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_archive == 0) ? 0 :
143*eda14cbcSMatt Macy 		    XAT0_ARCHIVE;
144*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE))
145*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_immutable == 0) ? 0 :
146*eda14cbcSMatt Macy 		    XAT0_IMMUTABLE;
147*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK))
148*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_nounlink == 0) ? 0 :
149*eda14cbcSMatt Macy 		    XAT0_NOUNLINK;
150*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY))
151*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_appendonly == 0) ? 0 :
152*eda14cbcSMatt Macy 		    XAT0_APPENDONLY;
153*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_OPAQUE))
154*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_opaque == 0) ? 0 :
155*eda14cbcSMatt Macy 		    XAT0_APPENDONLY;
156*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_NODUMP))
157*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_nodump == 0) ? 0 :
158*eda14cbcSMatt Macy 		    XAT0_NODUMP;
159*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED))
160*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_av_quarantined == 0) ? 0 :
161*eda14cbcSMatt Macy 		    XAT0_AV_QUARANTINED;
162*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED))
163*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_av_modified == 0) ? 0 :
164*eda14cbcSMatt Macy 		    XAT0_AV_MODIFIED;
165*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_CREATETIME))
166*eda14cbcSMatt Macy 		ZFS_TIME_ENCODE(&xoap->xoa_createtime, crtime);
167*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) {
168*eda14cbcSMatt Macy 		ASSERT(!XVA_ISSET_REQ(xvap, XAT_PROJID));
169*eda14cbcSMatt Macy 
170*eda14cbcSMatt Macy 		bcopy(xoap->xoa_av_scanstamp, scanstamp, AV_SCANSTAMP_SZ);
171*eda14cbcSMatt Macy 	} else if (XVA_ISSET_REQ(xvap, XAT_PROJID)) {
172*eda14cbcSMatt Macy 		/*
173*eda14cbcSMatt Macy 		 * XAT_PROJID and XAT_AV_SCANSTAMP will never be valid
174*eda14cbcSMatt Macy 		 * at the same time, so we can share the same space.
175*eda14cbcSMatt Macy 		 */
176*eda14cbcSMatt Macy 		bcopy(&xoap->xoa_projid, scanstamp, sizeof (uint64_t));
177*eda14cbcSMatt Macy 	}
178*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_REPARSE))
179*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_reparse == 0) ? 0 :
180*eda14cbcSMatt Macy 		    XAT0_REPARSE;
181*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_OFFLINE))
182*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_offline == 0) ? 0 :
183*eda14cbcSMatt Macy 		    XAT0_OFFLINE;
184*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_SPARSE))
185*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_sparse == 0) ? 0 :
186*eda14cbcSMatt Macy 		    XAT0_SPARSE;
187*eda14cbcSMatt Macy 	if (XVA_ISSET_REQ(xvap, XAT_PROJINHERIT))
188*eda14cbcSMatt Macy 		*attrs |= (xoap->xoa_projinherit == 0) ? 0 :
189*eda14cbcSMatt Macy 		    XAT0_PROJINHERIT;
190*eda14cbcSMatt Macy }
191*eda14cbcSMatt Macy 
192*eda14cbcSMatt Macy static void *
193*eda14cbcSMatt Macy zfs_log_fuid_ids(zfs_fuid_info_t *fuidp, void *start)
194*eda14cbcSMatt Macy {
195*eda14cbcSMatt Macy 	zfs_fuid_t *zfuid;
196*eda14cbcSMatt Macy 	uint64_t *fuidloc = start;
197*eda14cbcSMatt Macy 
198*eda14cbcSMatt Macy 	/* First copy in the ACE FUIDs */
199*eda14cbcSMatt Macy 	for (zfuid = list_head(&fuidp->z_fuids); zfuid;
200*eda14cbcSMatt Macy 	    zfuid = list_next(&fuidp->z_fuids, zfuid)) {
201*eda14cbcSMatt Macy 		*fuidloc++ = zfuid->z_logfuid;
202*eda14cbcSMatt Macy 	}
203*eda14cbcSMatt Macy 	return (fuidloc);
204*eda14cbcSMatt Macy }
205*eda14cbcSMatt Macy 
206*eda14cbcSMatt Macy 
207*eda14cbcSMatt Macy static void *
208*eda14cbcSMatt Macy zfs_log_fuid_domains(zfs_fuid_info_t *fuidp, void *start)
209*eda14cbcSMatt Macy {
210*eda14cbcSMatt Macy 	zfs_fuid_domain_t *zdomain;
211*eda14cbcSMatt Macy 
212*eda14cbcSMatt Macy 	/* now copy in the domain info, if any */
213*eda14cbcSMatt Macy 	if (fuidp->z_domain_str_sz != 0) {
214*eda14cbcSMatt Macy 		for (zdomain = list_head(&fuidp->z_domains); zdomain;
215*eda14cbcSMatt Macy 		    zdomain = list_next(&fuidp->z_domains, zdomain)) {
216*eda14cbcSMatt Macy 			bcopy((void *)zdomain->z_domain, start,
217*eda14cbcSMatt Macy 			    strlen(zdomain->z_domain) + 1);
218*eda14cbcSMatt Macy 			start = (caddr_t)start +
219*eda14cbcSMatt Macy 			    strlen(zdomain->z_domain) + 1;
220*eda14cbcSMatt Macy 		}
221*eda14cbcSMatt Macy 	}
222*eda14cbcSMatt Macy 	return (start);
223*eda14cbcSMatt Macy }
224*eda14cbcSMatt Macy 
225*eda14cbcSMatt Macy /*
226*eda14cbcSMatt Macy  * If zp is an xattr node, check whether the xattr owner is unlinked.
227*eda14cbcSMatt Macy  * We don't want to log anything if the owner is unlinked.
228*eda14cbcSMatt Macy  */
229*eda14cbcSMatt Macy static int
230*eda14cbcSMatt Macy zfs_xattr_owner_unlinked(znode_t *zp)
231*eda14cbcSMatt Macy {
232*eda14cbcSMatt Macy 	int unlinked = 0;
233*eda14cbcSMatt Macy 	znode_t *dzp;
234*eda14cbcSMatt Macy #ifdef __FreeBSD__
235*eda14cbcSMatt Macy 	znode_t *tzp = zp;
236*eda14cbcSMatt Macy 
237*eda14cbcSMatt Macy 	/*
238*eda14cbcSMatt Macy 	 * zrele drops the vnode lock which violates the VOP locking contract
239*eda14cbcSMatt Macy 	 * on FreeBSD. See comment at the top of zfs_replay.c for more detail.
240*eda14cbcSMatt Macy 	 */
241*eda14cbcSMatt Macy 	/*
242*eda14cbcSMatt Macy 	 * if zp is XATTR node, keep walking up via z_xattr_parent until we
243*eda14cbcSMatt Macy 	 * get the owner
244*eda14cbcSMatt Macy 	 */
245*eda14cbcSMatt Macy 	while (tzp->z_pflags & ZFS_XATTR) {
246*eda14cbcSMatt Macy 		ASSERT3U(zp->z_xattr_parent, !=, 0);
247*eda14cbcSMatt Macy 		if (zfs_zget(ZTOZSB(tzp), tzp->z_xattr_parent, &dzp) != 0) {
248*eda14cbcSMatt Macy 			unlinked = 1;
249*eda14cbcSMatt Macy 			break;
250*eda14cbcSMatt Macy 		}
251*eda14cbcSMatt Macy 
252*eda14cbcSMatt Macy 		if (tzp != zp)
253*eda14cbcSMatt Macy 			zrele(tzp);
254*eda14cbcSMatt Macy 		tzp = dzp;
255*eda14cbcSMatt Macy 		unlinked = tzp->z_unlinked;
256*eda14cbcSMatt Macy 	}
257*eda14cbcSMatt Macy 	if (tzp != zp)
258*eda14cbcSMatt Macy 		zrele(tzp);
259*eda14cbcSMatt Macy #else
260*eda14cbcSMatt Macy 	zhold(zp);
261*eda14cbcSMatt Macy 	/*
262*eda14cbcSMatt Macy 	 * if zp is XATTR node, keep walking up via z_xattr_parent until we
263*eda14cbcSMatt Macy 	 * get the owner
264*eda14cbcSMatt Macy 	 */
265*eda14cbcSMatt Macy 	while (zp->z_pflags & ZFS_XATTR) {
266*eda14cbcSMatt Macy 		ASSERT3U(zp->z_xattr_parent, !=, 0);
267*eda14cbcSMatt Macy 		if (zfs_zget(ZTOZSB(zp), zp->z_xattr_parent, &dzp) != 0) {
268*eda14cbcSMatt Macy 			unlinked = 1;
269*eda14cbcSMatt Macy 			break;
270*eda14cbcSMatt Macy 		}
271*eda14cbcSMatt Macy 
272*eda14cbcSMatt Macy 		zrele(zp);
273*eda14cbcSMatt Macy 		zp = dzp;
274*eda14cbcSMatt Macy 		unlinked = zp->z_unlinked;
275*eda14cbcSMatt Macy 	}
276*eda14cbcSMatt Macy 	zrele(zp);
277*eda14cbcSMatt Macy #endif
278*eda14cbcSMatt Macy 	return (unlinked);
279*eda14cbcSMatt Macy }
280*eda14cbcSMatt Macy 
281*eda14cbcSMatt Macy /*
282*eda14cbcSMatt Macy  * Handles TX_CREATE, TX_CREATE_ATTR, TX_MKDIR, TX_MKDIR_ATTR and
283*eda14cbcSMatt Macy  * TK_MKXATTR transactions.
284*eda14cbcSMatt Macy  *
285*eda14cbcSMatt Macy  * TX_CREATE and TX_MKDIR are standard creates, but they may have FUID
286*eda14cbcSMatt Macy  * domain information appended prior to the name.  In this case the
287*eda14cbcSMatt Macy  * uid/gid in the log record will be a log centric FUID.
288*eda14cbcSMatt Macy  *
289*eda14cbcSMatt Macy  * TX_CREATE_ACL_ATTR and TX_MKDIR_ACL_ATTR handle special creates that
290*eda14cbcSMatt Macy  * may contain attributes, ACL and optional fuid information.
291*eda14cbcSMatt Macy  *
292*eda14cbcSMatt Macy  * TX_CREATE_ACL and TX_MKDIR_ACL handle special creates that specify
293*eda14cbcSMatt Macy  * and ACL and normal users/groups in the ACEs.
294*eda14cbcSMatt Macy  *
295*eda14cbcSMatt Macy  * There may be an optional xvattr attribute information similar
296*eda14cbcSMatt Macy  * to zfs_log_setattr.
297*eda14cbcSMatt Macy  *
298*eda14cbcSMatt Macy  * Also, after the file name "domain" strings may be appended.
299*eda14cbcSMatt Macy  */
300*eda14cbcSMatt Macy void
301*eda14cbcSMatt Macy zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
302*eda14cbcSMatt Macy     znode_t *dzp, znode_t *zp, char *name, vsecattr_t *vsecp,
303*eda14cbcSMatt Macy     zfs_fuid_info_t *fuidp, vattr_t *vap)
304*eda14cbcSMatt Macy {
305*eda14cbcSMatt Macy 	itx_t *itx;
306*eda14cbcSMatt Macy 	lr_create_t *lr;
307*eda14cbcSMatt Macy 	lr_acl_create_t *lracl;
308*eda14cbcSMatt Macy 	size_t aclsize = 0;
309*eda14cbcSMatt Macy 	size_t xvatsize = 0;
310*eda14cbcSMatt Macy 	size_t txsize;
311*eda14cbcSMatt Macy 	xvattr_t *xvap = (xvattr_t *)vap;
312*eda14cbcSMatt Macy 	void *end;
313*eda14cbcSMatt Macy 	size_t lrsize;
314*eda14cbcSMatt Macy 	size_t namesize = strlen(name) + 1;
315*eda14cbcSMatt Macy 	size_t fuidsz = 0;
316*eda14cbcSMatt Macy 
317*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx) || zfs_xattr_owner_unlinked(dzp))
318*eda14cbcSMatt Macy 		return;
319*eda14cbcSMatt Macy 
320*eda14cbcSMatt Macy 	/*
321*eda14cbcSMatt Macy 	 * If we have FUIDs present then add in space for
322*eda14cbcSMatt Macy 	 * domains and ACE fuid's if any.
323*eda14cbcSMatt Macy 	 */
324*eda14cbcSMatt Macy 	if (fuidp) {
325*eda14cbcSMatt Macy 		fuidsz += fuidp->z_domain_str_sz;
326*eda14cbcSMatt Macy 		fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t);
327*eda14cbcSMatt Macy 	}
328*eda14cbcSMatt Macy 
329*eda14cbcSMatt Macy 	if (vap->va_mask & ATTR_XVATTR)
330*eda14cbcSMatt Macy 		xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize);
331*eda14cbcSMatt Macy 
332*eda14cbcSMatt Macy 	if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR ||
333*eda14cbcSMatt Macy 	    (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR ||
334*eda14cbcSMatt Macy 	    (int)txtype == TX_MKXATTR) {
335*eda14cbcSMatt Macy 		txsize = sizeof (*lr) + namesize + fuidsz + xvatsize;
336*eda14cbcSMatt Macy 		lrsize = sizeof (*lr);
337*eda14cbcSMatt Macy 	} else {
338*eda14cbcSMatt Macy 		txsize =
339*eda14cbcSMatt Macy 		    sizeof (lr_acl_create_t) + namesize + fuidsz +
340*eda14cbcSMatt Macy 		    ZIL_ACE_LENGTH(aclsize) + xvatsize;
341*eda14cbcSMatt Macy 		lrsize = sizeof (lr_acl_create_t);
342*eda14cbcSMatt Macy 	}
343*eda14cbcSMatt Macy 
344*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, txsize);
345*eda14cbcSMatt Macy 
346*eda14cbcSMatt Macy 	lr = (lr_create_t *)&itx->itx_lr;
347*eda14cbcSMatt Macy 	lr->lr_doid = dzp->z_id;
348*eda14cbcSMatt Macy 	lr->lr_foid = zp->z_id;
349*eda14cbcSMatt Macy 	/* Store dnode slot count in 8 bits above object id. */
350*eda14cbcSMatt Macy 	LR_FOID_SET_SLOTS(lr->lr_foid, zp->z_dnodesize >> DNODE_SHIFT);
351*eda14cbcSMatt Macy 	lr->lr_mode = zp->z_mode;
352*eda14cbcSMatt Macy 	if (!IS_EPHEMERAL(KUID_TO_SUID(ZTOUID(zp)))) {
353*eda14cbcSMatt Macy 		lr->lr_uid = (uint64_t)KUID_TO_SUID(ZTOUID(zp));
354*eda14cbcSMatt Macy 	} else {
355*eda14cbcSMatt Macy 		lr->lr_uid = fuidp->z_fuid_owner;
356*eda14cbcSMatt Macy 	}
357*eda14cbcSMatt Macy 	if (!IS_EPHEMERAL(KGID_TO_SGID(ZTOGID(zp)))) {
358*eda14cbcSMatt Macy 		lr->lr_gid = (uint64_t)KGID_TO_SGID(ZTOGID(zp));
359*eda14cbcSMatt Macy 	} else {
360*eda14cbcSMatt Macy 		lr->lr_gid = fuidp->z_fuid_group;
361*eda14cbcSMatt Macy 	}
362*eda14cbcSMatt Macy 	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen,
363*eda14cbcSMatt Macy 	    sizeof (uint64_t));
364*eda14cbcSMatt Macy 	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)),
365*eda14cbcSMatt Macy 	    lr->lr_crtime, sizeof (uint64_t) * 2);
366*eda14cbcSMatt Macy 
367*eda14cbcSMatt Macy 	if (sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(zp)), &lr->lr_rdev,
368*eda14cbcSMatt Macy 	    sizeof (lr->lr_rdev)) != 0)
369*eda14cbcSMatt Macy 		lr->lr_rdev = 0;
370*eda14cbcSMatt Macy 
371*eda14cbcSMatt Macy 	/*
372*eda14cbcSMatt Macy 	 * Fill in xvattr info if any
373*eda14cbcSMatt Macy 	 */
374*eda14cbcSMatt Macy 	if (vap->va_mask & ATTR_XVATTR) {
375*eda14cbcSMatt Macy 		zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap);
376*eda14cbcSMatt Macy 		end = (caddr_t)lr + lrsize + xvatsize;
377*eda14cbcSMatt Macy 	} else {
378*eda14cbcSMatt Macy 		end = (caddr_t)lr + lrsize;
379*eda14cbcSMatt Macy 	}
380*eda14cbcSMatt Macy 
381*eda14cbcSMatt Macy 	/* Now fill in any ACL info */
382*eda14cbcSMatt Macy 
383*eda14cbcSMatt Macy 	if (vsecp) {
384*eda14cbcSMatt Macy 		lracl = (lr_acl_create_t *)&itx->itx_lr;
385*eda14cbcSMatt Macy 		lracl->lr_aclcnt = vsecp->vsa_aclcnt;
386*eda14cbcSMatt Macy 		lracl->lr_acl_bytes = aclsize;
387*eda14cbcSMatt Macy 		lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
388*eda14cbcSMatt Macy 		lracl->lr_fuidcnt  = fuidp ? fuidp->z_fuid_cnt : 0;
389*eda14cbcSMatt Macy 		if (vsecp->vsa_aclflags & VSA_ACE_ACLFLAGS)
390*eda14cbcSMatt Macy 			lracl->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags;
391*eda14cbcSMatt Macy 		else
392*eda14cbcSMatt Macy 			lracl->lr_acl_flags = 0;
393*eda14cbcSMatt Macy 
394*eda14cbcSMatt Macy 		bcopy(vsecp->vsa_aclentp, end, aclsize);
395*eda14cbcSMatt Macy 		end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize);
396*eda14cbcSMatt Macy 	}
397*eda14cbcSMatt Macy 
398*eda14cbcSMatt Macy 	/* drop in FUID info */
399*eda14cbcSMatt Macy 	if (fuidp) {
400*eda14cbcSMatt Macy 		end = zfs_log_fuid_ids(fuidp, end);
401*eda14cbcSMatt Macy 		end = zfs_log_fuid_domains(fuidp, end);
402*eda14cbcSMatt Macy 	}
403*eda14cbcSMatt Macy 	/*
404*eda14cbcSMatt Macy 	 * Now place file name in log record
405*eda14cbcSMatt Macy 	 */
406*eda14cbcSMatt Macy 	bcopy(name, end, namesize);
407*eda14cbcSMatt Macy 
408*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
409*eda14cbcSMatt Macy }
410*eda14cbcSMatt Macy 
411*eda14cbcSMatt Macy /*
412*eda14cbcSMatt Macy  * Handles both TX_REMOVE and TX_RMDIR transactions.
413*eda14cbcSMatt Macy  */
414*eda14cbcSMatt Macy void
415*eda14cbcSMatt Macy zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
416*eda14cbcSMatt Macy     znode_t *dzp, char *name, uint64_t foid, boolean_t unlinked)
417*eda14cbcSMatt Macy {
418*eda14cbcSMatt Macy 	itx_t *itx;
419*eda14cbcSMatt Macy 	lr_remove_t *lr;
420*eda14cbcSMatt Macy 	size_t namesize = strlen(name) + 1;
421*eda14cbcSMatt Macy 
422*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx) || zfs_xattr_owner_unlinked(dzp))
423*eda14cbcSMatt Macy 		return;
424*eda14cbcSMatt Macy 
425*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
426*eda14cbcSMatt Macy 	lr = (lr_remove_t *)&itx->itx_lr;
427*eda14cbcSMatt Macy 	lr->lr_doid = dzp->z_id;
428*eda14cbcSMatt Macy 	bcopy(name, (char *)(lr + 1), namesize);
429*eda14cbcSMatt Macy 
430*eda14cbcSMatt Macy 	itx->itx_oid = foid;
431*eda14cbcSMatt Macy 
432*eda14cbcSMatt Macy 	/*
433*eda14cbcSMatt Macy 	 * Object ids can be re-instantiated in the next txg so
434*eda14cbcSMatt Macy 	 * remove any async transactions to avoid future leaks.
435*eda14cbcSMatt Macy 	 * This can happen if a fsync occurs on the re-instantiated
436*eda14cbcSMatt Macy 	 * object for a WR_INDIRECT or WR_NEED_COPY write, which gets
437*eda14cbcSMatt Macy 	 * the new file data and flushes a write record for the old object.
438*eda14cbcSMatt Macy 	 */
439*eda14cbcSMatt Macy 	if (unlinked) {
440*eda14cbcSMatt Macy 		ASSERT((txtype & ~TX_CI) == TX_REMOVE);
441*eda14cbcSMatt Macy 		zil_remove_async(zilog, foid);
442*eda14cbcSMatt Macy 	}
443*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
444*eda14cbcSMatt Macy }
445*eda14cbcSMatt Macy 
446*eda14cbcSMatt Macy /*
447*eda14cbcSMatt Macy  * Handles TX_LINK transactions.
448*eda14cbcSMatt Macy  */
449*eda14cbcSMatt Macy void
450*eda14cbcSMatt Macy zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
451*eda14cbcSMatt Macy     znode_t *dzp, znode_t *zp, char *name)
452*eda14cbcSMatt Macy {
453*eda14cbcSMatt Macy 	itx_t *itx;
454*eda14cbcSMatt Macy 	lr_link_t *lr;
455*eda14cbcSMatt Macy 	size_t namesize = strlen(name) + 1;
456*eda14cbcSMatt Macy 
457*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx))
458*eda14cbcSMatt Macy 		return;
459*eda14cbcSMatt Macy 
460*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
461*eda14cbcSMatt Macy 	lr = (lr_link_t *)&itx->itx_lr;
462*eda14cbcSMatt Macy 	lr->lr_doid = dzp->z_id;
463*eda14cbcSMatt Macy 	lr->lr_link_obj = zp->z_id;
464*eda14cbcSMatt Macy 	bcopy(name, (char *)(lr + 1), namesize);
465*eda14cbcSMatt Macy 
466*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
467*eda14cbcSMatt Macy }
468*eda14cbcSMatt Macy 
469*eda14cbcSMatt Macy /*
470*eda14cbcSMatt Macy  * Handles TX_SYMLINK transactions.
471*eda14cbcSMatt Macy  */
472*eda14cbcSMatt Macy void
473*eda14cbcSMatt Macy zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
474*eda14cbcSMatt Macy     znode_t *dzp, znode_t *zp, char *name, char *link)
475*eda14cbcSMatt Macy {
476*eda14cbcSMatt Macy 	itx_t *itx;
477*eda14cbcSMatt Macy 	lr_create_t *lr;
478*eda14cbcSMatt Macy 	size_t namesize = strlen(name) + 1;
479*eda14cbcSMatt Macy 	size_t linksize = strlen(link) + 1;
480*eda14cbcSMatt Macy 
481*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx))
482*eda14cbcSMatt Macy 		return;
483*eda14cbcSMatt Macy 
484*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize);
485*eda14cbcSMatt Macy 	lr = (lr_create_t *)&itx->itx_lr;
486*eda14cbcSMatt Macy 	lr->lr_doid = dzp->z_id;
487*eda14cbcSMatt Macy 	lr->lr_foid = zp->z_id;
488*eda14cbcSMatt Macy 	lr->lr_uid = KUID_TO_SUID(ZTOUID(zp));
489*eda14cbcSMatt Macy 	lr->lr_gid = KGID_TO_SGID(ZTOGID(zp));
490*eda14cbcSMatt Macy 	lr->lr_mode = zp->z_mode;
491*eda14cbcSMatt Macy 	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen,
492*eda14cbcSMatt Macy 	    sizeof (uint64_t));
493*eda14cbcSMatt Macy 	(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)),
494*eda14cbcSMatt Macy 	    lr->lr_crtime, sizeof (uint64_t) * 2);
495*eda14cbcSMatt Macy 	bcopy(name, (char *)(lr + 1), namesize);
496*eda14cbcSMatt Macy 	bcopy(link, (char *)(lr + 1) + namesize, linksize);
497*eda14cbcSMatt Macy 
498*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
499*eda14cbcSMatt Macy }
500*eda14cbcSMatt Macy 
501*eda14cbcSMatt Macy /*
502*eda14cbcSMatt Macy  * Handles TX_RENAME transactions.
503*eda14cbcSMatt Macy  */
504*eda14cbcSMatt Macy void
505*eda14cbcSMatt Macy zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
506*eda14cbcSMatt Macy     znode_t *sdzp, char *sname, znode_t *tdzp, char *dname, znode_t *szp)
507*eda14cbcSMatt Macy {
508*eda14cbcSMatt Macy 	itx_t *itx;
509*eda14cbcSMatt Macy 	lr_rename_t *lr;
510*eda14cbcSMatt Macy 	size_t snamesize = strlen(sname) + 1;
511*eda14cbcSMatt Macy 	size_t dnamesize = strlen(dname) + 1;
512*eda14cbcSMatt Macy 
513*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx))
514*eda14cbcSMatt Macy 		return;
515*eda14cbcSMatt Macy 
516*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
517*eda14cbcSMatt Macy 	lr = (lr_rename_t *)&itx->itx_lr;
518*eda14cbcSMatt Macy 	lr->lr_sdoid = sdzp->z_id;
519*eda14cbcSMatt Macy 	lr->lr_tdoid = tdzp->z_id;
520*eda14cbcSMatt Macy 	bcopy(sname, (char *)(lr + 1), snamesize);
521*eda14cbcSMatt Macy 	bcopy(dname, (char *)(lr + 1) + snamesize, dnamesize);
522*eda14cbcSMatt Macy 	itx->itx_oid = szp->z_id;
523*eda14cbcSMatt Macy 
524*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
525*eda14cbcSMatt Macy }
526*eda14cbcSMatt Macy 
527*eda14cbcSMatt Macy /*
528*eda14cbcSMatt Macy  * zfs_log_write() handles TX_WRITE transactions. The specified callback is
529*eda14cbcSMatt Macy  * called as soon as the write is on stable storage (be it via a DMU sync or a
530*eda14cbcSMatt Macy  * ZIL commit).
531*eda14cbcSMatt Macy  */
532*eda14cbcSMatt Macy long zfs_immediate_write_sz = 32768;
533*eda14cbcSMatt Macy 
534*eda14cbcSMatt Macy void
535*eda14cbcSMatt Macy zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
536*eda14cbcSMatt Macy     znode_t *zp, offset_t off, ssize_t resid, int ioflag,
537*eda14cbcSMatt Macy     zil_callback_t callback, void *callback_data)
538*eda14cbcSMatt Macy {
539*eda14cbcSMatt Macy 	dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl);
540*eda14cbcSMatt Macy 	uint32_t blocksize = zp->z_blksz;
541*eda14cbcSMatt Macy 	itx_wr_state_t write_state;
542*eda14cbcSMatt Macy 	uintptr_t fsync_cnt;
543*eda14cbcSMatt Macy 
544*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx) || zp->z_unlinked ||
545*eda14cbcSMatt Macy 	    zfs_xattr_owner_unlinked(zp)) {
546*eda14cbcSMatt Macy 		if (callback != NULL)
547*eda14cbcSMatt Macy 			callback(callback_data);
548*eda14cbcSMatt Macy 		return;
549*eda14cbcSMatt Macy 	}
550*eda14cbcSMatt Macy 
551*eda14cbcSMatt Macy 	if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
552*eda14cbcSMatt Macy 		write_state = WR_INDIRECT;
553*eda14cbcSMatt Macy 	else if (!spa_has_slogs(zilog->zl_spa) &&
554*eda14cbcSMatt Macy 	    resid >= zfs_immediate_write_sz)
555*eda14cbcSMatt Macy 		write_state = WR_INDIRECT;
556*eda14cbcSMatt Macy 	else if (ioflag & (O_SYNC | O_DSYNC))
557*eda14cbcSMatt Macy 		write_state = WR_COPIED;
558*eda14cbcSMatt Macy 	else
559*eda14cbcSMatt Macy 		write_state = WR_NEED_COPY;
560*eda14cbcSMatt Macy 
561*eda14cbcSMatt Macy 	if ((fsync_cnt = (uintptr_t)tsd_get(zfs_fsyncer_key)) != 0) {
562*eda14cbcSMatt Macy 		(void) tsd_set(zfs_fsyncer_key, (void *)(fsync_cnt - 1));
563*eda14cbcSMatt Macy 	}
564*eda14cbcSMatt Macy 
565*eda14cbcSMatt Macy 	while (resid) {
566*eda14cbcSMatt Macy 		itx_t *itx;
567*eda14cbcSMatt Macy 		lr_write_t *lr;
568*eda14cbcSMatt Macy 		itx_wr_state_t wr_state = write_state;
569*eda14cbcSMatt Macy 		ssize_t len = resid;
570*eda14cbcSMatt Macy 
571*eda14cbcSMatt Macy 		/*
572*eda14cbcSMatt Macy 		 * A WR_COPIED record must fit entirely in one log block.
573*eda14cbcSMatt Macy 		 * Large writes can use WR_NEED_COPY, which the ZIL will
574*eda14cbcSMatt Macy 		 * split into multiple records across several log blocks
575*eda14cbcSMatt Macy 		 * if necessary.
576*eda14cbcSMatt Macy 		 */
577*eda14cbcSMatt Macy 		if (wr_state == WR_COPIED &&
578*eda14cbcSMatt Macy 		    resid > zil_max_copied_data(zilog))
579*eda14cbcSMatt Macy 			wr_state = WR_NEED_COPY;
580*eda14cbcSMatt Macy 		else if (wr_state == WR_INDIRECT)
581*eda14cbcSMatt Macy 			len = MIN(blocksize - P2PHASE(off, blocksize), resid);
582*eda14cbcSMatt Macy 
583*eda14cbcSMatt Macy 		itx = zil_itx_create(txtype, sizeof (*lr) +
584*eda14cbcSMatt Macy 		    (wr_state == WR_COPIED ? len : 0));
585*eda14cbcSMatt Macy 		lr = (lr_write_t *)&itx->itx_lr;
586*eda14cbcSMatt Macy 
587*eda14cbcSMatt Macy 		DB_DNODE_ENTER(db);
588*eda14cbcSMatt Macy 		if (wr_state == WR_COPIED && dmu_read_by_dnode(DB_DNODE(db),
589*eda14cbcSMatt Macy 		    off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) {
590*eda14cbcSMatt Macy 			zil_itx_destroy(itx);
591*eda14cbcSMatt Macy 			itx = zil_itx_create(txtype, sizeof (*lr));
592*eda14cbcSMatt Macy 			lr = (lr_write_t *)&itx->itx_lr;
593*eda14cbcSMatt Macy 			wr_state = WR_NEED_COPY;
594*eda14cbcSMatt Macy 		}
595*eda14cbcSMatt Macy 		DB_DNODE_EXIT(db);
596*eda14cbcSMatt Macy 
597*eda14cbcSMatt Macy 		itx->itx_wr_state = wr_state;
598*eda14cbcSMatt Macy 		lr->lr_foid = zp->z_id;
599*eda14cbcSMatt Macy 		lr->lr_offset = off;
600*eda14cbcSMatt Macy 		lr->lr_length = len;
601*eda14cbcSMatt Macy 		lr->lr_blkoff = 0;
602*eda14cbcSMatt Macy 		BP_ZERO(&lr->lr_blkptr);
603*eda14cbcSMatt Macy 
604*eda14cbcSMatt Macy 		itx->itx_private = ZTOZSB(zp);
605*eda14cbcSMatt Macy 
606*eda14cbcSMatt Macy 		if (!(ioflag & (O_SYNC | O_DSYNC)) && (zp->z_sync_cnt == 0) &&
607*eda14cbcSMatt Macy 		    (fsync_cnt == 0))
608*eda14cbcSMatt Macy 			itx->itx_sync = B_FALSE;
609*eda14cbcSMatt Macy 
610*eda14cbcSMatt Macy 		itx->itx_callback = callback;
611*eda14cbcSMatt Macy 		itx->itx_callback_data = callback_data;
612*eda14cbcSMatt Macy 		zil_itx_assign(zilog, itx, tx);
613*eda14cbcSMatt Macy 
614*eda14cbcSMatt Macy 		off += len;
615*eda14cbcSMatt Macy 		resid -= len;
616*eda14cbcSMatt Macy 	}
617*eda14cbcSMatt Macy }
618*eda14cbcSMatt Macy 
619*eda14cbcSMatt Macy /*
620*eda14cbcSMatt Macy  * Handles TX_TRUNCATE transactions.
621*eda14cbcSMatt Macy  */
622*eda14cbcSMatt Macy void
623*eda14cbcSMatt Macy zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
624*eda14cbcSMatt Macy     znode_t *zp, uint64_t off, uint64_t len)
625*eda14cbcSMatt Macy {
626*eda14cbcSMatt Macy 	itx_t *itx;
627*eda14cbcSMatt Macy 	lr_truncate_t *lr;
628*eda14cbcSMatt Macy 
629*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx) || zp->z_unlinked ||
630*eda14cbcSMatt Macy 	    zfs_xattr_owner_unlinked(zp))
631*eda14cbcSMatt Macy 		return;
632*eda14cbcSMatt Macy 
633*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, sizeof (*lr));
634*eda14cbcSMatt Macy 	lr = (lr_truncate_t *)&itx->itx_lr;
635*eda14cbcSMatt Macy 	lr->lr_foid = zp->z_id;
636*eda14cbcSMatt Macy 	lr->lr_offset = off;
637*eda14cbcSMatt Macy 	lr->lr_length = len;
638*eda14cbcSMatt Macy 
639*eda14cbcSMatt Macy 	itx->itx_sync = (zp->z_sync_cnt != 0);
640*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
641*eda14cbcSMatt Macy }
642*eda14cbcSMatt Macy 
643*eda14cbcSMatt Macy /*
644*eda14cbcSMatt Macy  * Handles TX_SETATTR transactions.
645*eda14cbcSMatt Macy  */
646*eda14cbcSMatt Macy void
647*eda14cbcSMatt Macy zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
648*eda14cbcSMatt Macy     znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp)
649*eda14cbcSMatt Macy {
650*eda14cbcSMatt Macy 	itx_t		*itx;
651*eda14cbcSMatt Macy 	lr_setattr_t	*lr;
652*eda14cbcSMatt Macy 	xvattr_t	*xvap = (xvattr_t *)vap;
653*eda14cbcSMatt Macy 	size_t		recsize = sizeof (lr_setattr_t);
654*eda14cbcSMatt Macy 	void		*start;
655*eda14cbcSMatt Macy 
656*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx) || zp->z_unlinked)
657*eda14cbcSMatt Macy 		return;
658*eda14cbcSMatt Macy 
659*eda14cbcSMatt Macy 	/*
660*eda14cbcSMatt Macy 	 * If XVATTR set, then log record size needs to allow
661*eda14cbcSMatt Macy 	 * for lr_attr_t + xvattr mask, mapsize and create time
662*eda14cbcSMatt Macy 	 * plus actual attribute values
663*eda14cbcSMatt Macy 	 */
664*eda14cbcSMatt Macy 	if (vap->va_mask & ATTR_XVATTR)
665*eda14cbcSMatt Macy 		recsize = sizeof (*lr) + ZIL_XVAT_SIZE(xvap->xva_mapsize);
666*eda14cbcSMatt Macy 
667*eda14cbcSMatt Macy 	if (fuidp)
668*eda14cbcSMatt Macy 		recsize += fuidp->z_domain_str_sz;
669*eda14cbcSMatt Macy 
670*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, recsize);
671*eda14cbcSMatt Macy 	lr = (lr_setattr_t *)&itx->itx_lr;
672*eda14cbcSMatt Macy 	lr->lr_foid = zp->z_id;
673*eda14cbcSMatt Macy 	lr->lr_mask = (uint64_t)mask_applied;
674*eda14cbcSMatt Macy 	lr->lr_mode = (uint64_t)vap->va_mode;
675*eda14cbcSMatt Macy 	if ((mask_applied & ATTR_UID) && IS_EPHEMERAL(vap->va_uid))
676*eda14cbcSMatt Macy 		lr->lr_uid = fuidp->z_fuid_owner;
677*eda14cbcSMatt Macy 	else
678*eda14cbcSMatt Macy 		lr->lr_uid = (uint64_t)vap->va_uid;
679*eda14cbcSMatt Macy 
680*eda14cbcSMatt Macy 	if ((mask_applied & ATTR_GID) && IS_EPHEMERAL(vap->va_gid))
681*eda14cbcSMatt Macy 		lr->lr_gid = fuidp->z_fuid_group;
682*eda14cbcSMatt Macy 	else
683*eda14cbcSMatt Macy 		lr->lr_gid = (uint64_t)vap->va_gid;
684*eda14cbcSMatt Macy 
685*eda14cbcSMatt Macy 	lr->lr_size = (uint64_t)vap->va_size;
686*eda14cbcSMatt Macy 	ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime);
687*eda14cbcSMatt Macy 	ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime);
688*eda14cbcSMatt Macy 	start = (lr_setattr_t *)(lr + 1);
689*eda14cbcSMatt Macy 	if (vap->va_mask & ATTR_XVATTR) {
690*eda14cbcSMatt Macy 		zfs_log_xvattr((lr_attr_t *)start, xvap);
691*eda14cbcSMatt Macy 		start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize);
692*eda14cbcSMatt Macy 	}
693*eda14cbcSMatt Macy 
694*eda14cbcSMatt Macy 	/*
695*eda14cbcSMatt Macy 	 * Now stick on domain information if any on end
696*eda14cbcSMatt Macy 	 */
697*eda14cbcSMatt Macy 
698*eda14cbcSMatt Macy 	if (fuidp)
699*eda14cbcSMatt Macy 		(void) zfs_log_fuid_domains(fuidp, start);
700*eda14cbcSMatt Macy 
701*eda14cbcSMatt Macy 	itx->itx_sync = (zp->z_sync_cnt != 0);
702*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
703*eda14cbcSMatt Macy }
704*eda14cbcSMatt Macy 
705*eda14cbcSMatt Macy /*
706*eda14cbcSMatt Macy  * Handles TX_ACL transactions.
707*eda14cbcSMatt Macy  */
708*eda14cbcSMatt Macy void
709*eda14cbcSMatt Macy zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
710*eda14cbcSMatt Macy     vsecattr_t *vsecp, zfs_fuid_info_t *fuidp)
711*eda14cbcSMatt Macy {
712*eda14cbcSMatt Macy 	itx_t *itx;
713*eda14cbcSMatt Macy 	lr_acl_v0_t *lrv0;
714*eda14cbcSMatt Macy 	lr_acl_t *lr;
715*eda14cbcSMatt Macy 	int txtype;
716*eda14cbcSMatt Macy 	int lrsize;
717*eda14cbcSMatt Macy 	size_t txsize;
718*eda14cbcSMatt Macy 	size_t aclbytes = vsecp->vsa_aclentsz;
719*eda14cbcSMatt Macy 
720*eda14cbcSMatt Macy 	if (zil_replaying(zilog, tx) || zp->z_unlinked)
721*eda14cbcSMatt Macy 		return;
722*eda14cbcSMatt Macy 
723*eda14cbcSMatt Macy 	txtype = (ZTOZSB(zp)->z_version < ZPL_VERSION_FUID) ?
724*eda14cbcSMatt Macy 	    TX_ACL_V0 : TX_ACL;
725*eda14cbcSMatt Macy 
726*eda14cbcSMatt Macy 	if (txtype == TX_ACL)
727*eda14cbcSMatt Macy 		lrsize = sizeof (*lr);
728*eda14cbcSMatt Macy 	else
729*eda14cbcSMatt Macy 		lrsize = sizeof (*lrv0);
730*eda14cbcSMatt Macy 
731*eda14cbcSMatt Macy 	txsize = lrsize +
732*eda14cbcSMatt Macy 	    ((txtype == TX_ACL) ? ZIL_ACE_LENGTH(aclbytes) : aclbytes) +
733*eda14cbcSMatt Macy 	    (fuidp ? fuidp->z_domain_str_sz : 0) +
734*eda14cbcSMatt Macy 	    sizeof (uint64_t) * (fuidp ? fuidp->z_fuid_cnt : 0);
735*eda14cbcSMatt Macy 
736*eda14cbcSMatt Macy 	itx = zil_itx_create(txtype, txsize);
737*eda14cbcSMatt Macy 
738*eda14cbcSMatt Macy 	lr = (lr_acl_t *)&itx->itx_lr;
739*eda14cbcSMatt Macy 	lr->lr_foid = zp->z_id;
740*eda14cbcSMatt Macy 	if (txtype == TX_ACL) {
741*eda14cbcSMatt Macy 		lr->lr_acl_bytes = aclbytes;
742*eda14cbcSMatt Macy 		lr->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
743*eda14cbcSMatt Macy 		lr->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0;
744*eda14cbcSMatt Macy 		if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS)
745*eda14cbcSMatt Macy 			lr->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags;
746*eda14cbcSMatt Macy 		else
747*eda14cbcSMatt Macy 			lr->lr_acl_flags = 0;
748*eda14cbcSMatt Macy 	}
749*eda14cbcSMatt Macy 	lr->lr_aclcnt = (uint64_t)vsecp->vsa_aclcnt;
750*eda14cbcSMatt Macy 
751*eda14cbcSMatt Macy 	if (txtype == TX_ACL_V0) {
752*eda14cbcSMatt Macy 		lrv0 = (lr_acl_v0_t *)lr;
753*eda14cbcSMatt Macy 		bcopy(vsecp->vsa_aclentp, (ace_t *)(lrv0 + 1), aclbytes);
754*eda14cbcSMatt Macy 	} else {
755*eda14cbcSMatt Macy 		void *start = (ace_t *)(lr + 1);
756*eda14cbcSMatt Macy 
757*eda14cbcSMatt Macy 		bcopy(vsecp->vsa_aclentp, start, aclbytes);
758*eda14cbcSMatt Macy 
759*eda14cbcSMatt Macy 		start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes);
760*eda14cbcSMatt Macy 
761*eda14cbcSMatt Macy 		if (fuidp) {
762*eda14cbcSMatt Macy 			start = zfs_log_fuid_ids(fuidp, start);
763*eda14cbcSMatt Macy 			(void) zfs_log_fuid_domains(fuidp, start);
764*eda14cbcSMatt Macy 		}
765*eda14cbcSMatt Macy 	}
766*eda14cbcSMatt Macy 
767*eda14cbcSMatt Macy 	itx->itx_sync = (zp->z_sync_cnt != 0);
768*eda14cbcSMatt Macy 	zil_itx_assign(zilog, itx, tx);
769*eda14cbcSMatt Macy }
770*eda14cbcSMatt Macy 
771*eda14cbcSMatt Macy /* BEGIN CSTYLED */
772*eda14cbcSMatt Macy ZFS_MODULE_PARAM(zfs, zfs_, immediate_write_sz, LONG, ZMOD_RW,
773*eda14cbcSMatt Macy 	"Largest data block to write to zil");
774*eda14cbcSMatt Macy /* END CSTYLED */
775