1fa9e406ahrens/*
2fa9e406ahrens * CDDL HEADER START
3fa9e406ahrens *
4fa9e406ahrens * The contents of this file are subject to the terms of the
572fc53bmarks * Common Development and Distribution License (the "License").
672fc53bmarks * You may not use this file except in compliance with the License.
7fa9e406ahrens *
8fa9e406ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e406ahrens * or http://www.opensolaris.org/os/licensing.
10fa9e406ahrens * See the License for the specific language governing permissions
11fa9e406ahrens * and limitations under the License.
12fa9e406ahrens *
13fa9e406ahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e406ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e406ahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e406ahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e406ahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e406ahrens *
19fa9e406ahrens * CDDL HEADER END
20fa9e406ahrens */
21fa9e406ahrens/*
2291de656Neil Perrin * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
239a686fbPaul Dagnelie * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
24fa9e406ahrens */
25fa9e406ahrens
26fa9e406ahrens#include <sys/types.h>
27fa9e406ahrens#include <sys/param.h>
28fa9e406ahrens#include <sys/systm.h>
29fa9e406ahrens#include <sys/sysmacros.h>
30fa9e406ahrens#include <sys/cmn_err.h>
31fa9e406ahrens#include <sys/kmem.h>
32fa9e406ahrens#include <sys/thread.h>
33fa9e406ahrens#include <sys/file.h>
34fa9e406ahrens#include <sys/fcntl.h>
35fa9e406ahrens#include <sys/vfs.h>
36fa9e406ahrens#include <sys/fs/zfs.h>
37fa9e406ahrens#include <sys/zfs_znode.h>
38fa9e406ahrens#include <sys/zfs_dir.h>
39fa9e406ahrens#include <sys/zfs_acl.h>
40da6c28aamw#include <sys/zfs_fuid.h>
41fa9e406ahrens#include <sys/spa.h>
42fa9e406ahrens#include <sys/zil.h>
43fa9e406ahrens#include <sys/byteorder.h>
44fa9e406ahrens#include <sys/stat.h>
45fa9e406ahrens#include <sys/mode.h>
46fa9e406ahrens#include <sys/acl.h>
47fa9e406ahrens#include <sys/atomic.h>
48fa9e406ahrens#include <sys/cred.h>
49fa9e406ahrens
50fa9e406ahrens/*
51fa9e406ahrens * Functions to replay ZFS intent log (ZIL) records
52fa9e406ahrens * The functions are called through a function vector (zfs_replay_vector)
53fa9e406ahrens * which is indexed by the transaction type.
54fa9e406ahrens */
55fa9e406ahrens
56fa9e406ahrensstatic void
57fa9e406ahrenszfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode,
589a686fbPaul Dagnelie    uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid)
59fa9e406ahrens{
60fa9e406ahrens	bzero(vap, sizeof (*vap));
61fa9e406ahrens	vap->va_mask = (uint_t)mask;
62fa9e406ahrens	vap->va_type = IFTOVT(mode);
63fa9e406ahrens	vap->va_mode = mode & MODEMASK;
64da6c28aamw	vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
65da6c28aamw	vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
6672fc53bmarks	vap->va_rdev = zfs_cmpldev(rdev);
67fa9e406ahrens	vap->va_nodeid = nodeid;
68fa9e406ahrens}
69fa9e406ahrens
70fa9e406ahrens/* ARGSUSED */
71fa9e406ahrensstatic int
723f7978dAlan Somerszfs_replay_error(void *arg1, void *arg2, boolean_t byteswap)
73fa9e406ahrens{
74be6fd75Matthew Ahrens	return (SET_ERROR(ENOTSUP));
75fa9e406ahrens}
76fa9e406ahrens
77da6c28aamwstatic void
78da6c28aamwzfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
79da6c28aamw{
80da6c28aamw	xoptattr_t *xoap = NULL;
81da6c28aamw	uint64_t *attrs;
82da6c28aamw	uint64_t *crtime;
83569e6c6marks	uint32_t *bitmap;
84da6c28aamw	void *scanstamp;
85569e6c6marks	int i;
86da6c28aamw
87da6c28aamw	xvap->xva_vattr.va_mask |= AT_XVATTR;
88da6c28aamw	if ((xoap = xva_getxoptattr(xvap)) == NULL) {
89da6c28aamw		xvap->xva_vattr.va_mask &= ~AT_XVATTR; /* shouldn't happen */
90da6c28aamw		return;
91da6c28aamw	}
92da6c28aamw
93da6c28aamw	ASSERT(lrattr->lr_attr_masksize == xvap->xva_mapsize);
94569e6c6marks
95569e6c6marks	bitmap = &lrattr->lr_attr_bitmap;
96569e6c6marks	for (i = 0; i != lrattr->lr_attr_masksize; i++, bitmap++)
97569e6c6marks		xvap->xva_reqattrmap[i] = *bitmap;
98569e6c6marks
99da6c28aamw	attrs = (uint64_t *)(lrattr + lrattr->lr_attr_masksize - 1);
100da6c28aamw	crtime = attrs + 1;
101da6c28aamw	scanstamp = (caddr_t)(crtime + 2);
102da6c28aamw
103da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_HIDDEN))
104da6c28aamw		xoap->xoa_hidden = ((*attrs & XAT0_HIDDEN) != 0);
105da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_SYSTEM))
106da6c28aamw		xoap->xoa_system = ((*attrs & XAT0_SYSTEM) != 0);
107da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE))
108da6c28aamw		xoap->xoa_archive = ((*attrs & XAT0_ARCHIVE) != 0);
109da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_READONLY))
110da6c28aamw		xoap->xoa_readonly = ((*attrs & XAT0_READONLY) != 0);
111da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE))
112da6c28aamw		xoap->xoa_immutable = ((*attrs & XAT0_IMMUTABLE) != 0);
113da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK))
114da6c28aamw		xoap->xoa_nounlink = ((*attrs & XAT0_NOUNLINK) != 0);
115da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY))
116da6c28aamw		xoap->xoa_appendonly = ((*attrs & XAT0_APPENDONLY) != 0);
117da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_NODUMP))
118da6c28aamw		xoap->xoa_nodump = ((*attrs & XAT0_NODUMP) != 0);
119da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_OPAQUE))
120da6c28aamw		xoap->xoa_opaque = ((*attrs & XAT0_OPAQUE) != 0);
121da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED))
122da6c28aamw		xoap->xoa_av_modified = ((*attrs & XAT0_AV_MODIFIED) != 0);
123da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED))
124da6c28aamw		xoap->xoa_av_quarantined =
125da6c28aamw		    ((*attrs & XAT0_AV_QUARANTINED) != 0);
126da6c28aamw	if (XVA_ISSET_REQ(xvap, XAT_CREATETIME))
127da6c28aamw		ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime);
128f67950bNasf-Fan	if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) {
129f67950bNasf-Fan		ASSERT(!XVA_ISSET_REQ(xvap, XAT_PROJID));
130f67950bNasf-Fan
131da6c28aamw		bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ);
132f67950bNasf-Fan	} else if (XVA_ISSET_REQ(xvap, XAT_PROJID)) {
133f67950bNasf-Fan		/*
134f67950bNasf-Fan		 * XAT_PROJID and XAT_AV_SCANSTAMP will never be valid
135f67950bNasf-Fan		 * at the same time, so we can share the same space.
136f67950bNasf-Fan		 */
137f67950bNasf-Fan		bcopy(scanstamp, &xoap->xoa_projid, sizeof (uint64_t));
138f67950bNasf-Fan	}
1397a286c4Dai Ngo	if (XVA_ISSET_REQ(xvap, XAT_REPARSE))
1407a286c4Dai Ngo		xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0);
141fd9ee8bjoyce mcintosh	if (XVA_ISSET_REQ(xvap, XAT_OFFLINE))
142fd9ee8bjoyce mcintosh		xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0);
143fd9ee8bjoyce mcintosh	if (XVA_ISSET_REQ(xvap, XAT_SPARSE))
144fd9ee8bjoyce mcintosh		xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0);
145f67950bNasf-Fan	if (XVA_ISSET_REQ(xvap, XAT_PROJINHERIT))
146f67950bNasf-Fan		xoap->xoa_projinherit = ((*attrs & XAT0_PROJINHERIT) != 0);
147da6c28aamw}
148da6c28aamw
149da6c28aamwstatic int
150da6c28aamwzfs_replay_domain_cnt(uint64_t uid, uint64_t gid)
151da6c28aamw{
152da6c28aamw	uint64_t uid_idx;
153da6c28aamw	uint64_t gid_idx;
154da6c28aamw	int domcnt = 0;
155da6c28aamw
156da6c28aamw	uid_idx = FUID_INDEX(uid);
157da6c28aamw	gid_idx = FUID_INDEX(gid);
158da6c28aamw	if (uid_idx)
159da6c28aamw		domcnt++;
160da6c28aamw	if (gid_idx > 0 && gid_idx != uid_idx)
161da6c28aamw		domcnt++;
162da6c28aamw
163da6c28aamw	return (domcnt);
164da6c28aamw}
165da6c28aamw
166da6c28aamwstatic void *
167da6c28aamwzfs_replay_fuid_domain_common(zfs_fuid_info_t *fuid_infop, void *start,
168da6c28aamw    int domcnt)
169da6c28aamw{
170da6c28aamw	int i;
171da6c28aamw
172da6c28aamw	for (i = 0; i != domcnt; i++) {
173da6c28aamw		fuid_infop->z_domain_table[i] = start;
174da6c28aamw		start = (caddr_t)start + strlen(start) + 1;
175da6c28aamw	}
176da6c28aamw
177da6c28aamw	return (start);
178da6c28aamw}
179da6c28aamw
180da6c28aamw/*
181da6c28aamw * Set the uid/gid in the fuid_info structure.
182da6c28aamw */
183da6c28aamwstatic void
184da6c28aamwzfs_replay_fuid_ugid(zfs_fuid_info_t *fuid_infop, uint64_t uid, uint64_t gid)
185da6c28aamw{
186da6c28aamw	/*
187da6c28aamw	 * If owner or group are log specific FUIDs then slurp up
188da6c28aamw	 * domain information and build zfs_fuid_info_t
189da6c28aamw	 */
190da6c28aamw	if (IS_EPHEMERAL(uid))
191da6c28aamw		fuid_infop->z_fuid_owner = uid;
192da6c28aamw
193da6c28aamw	if (IS_EPHEMERAL(gid))
194da6c28aamw		fuid_infop->z_fuid_group = gid;
195da6c28aamw}
196da6c28aamw
197da6c28aamw/*
198da6c28aamw * Load fuid domains into fuid_info_t
199da6c28aamw */
200da6c28aamwstatic zfs_fuid_info_t *
201da6c28aamwzfs_replay_fuid_domain(void *buf, void **end, uint64_t uid, uint64_t gid)
202da6c28aamw{
203da6c28aamw	int domcnt;
204da6c28aamw
205da6c28aamw	zfs_fuid_info_t *fuid_infop;
206da6c28aamw
207da6c28aamw	fuid_infop = zfs_fuid_info_alloc();
208da6c28aamw
209da6c28aamw	domcnt = zfs_replay_domain_cnt(uid, gid);
210da6c28aamw
211da6c28aamw	if (domcnt == 0)
212da6c28aamw		return (fuid_infop);
213da6c28aamw
214da6c28aamw	fuid_infop->z_domain_table =
215da6c28aamw	    kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP);
216da6c28aamw
217da6c28aamw	zfs_replay_fuid_ugid(fuid_infop, uid, gid);
218da6c28aamw
219da6c28aamw	fuid_infop->z_domain_cnt = domcnt;
220da6c28aamw	*end = zfs_replay_fuid_domain_common(fuid_infop, buf, domcnt);
221da6c28aamw	return (fuid_infop);
222da6c28aamw}
223da6c28aamw
224da6c28aamw/*
225da6c28aamw * load zfs_fuid_t's and fuid_domains into fuid_info_t
226da6c28aamw */
227da6c28aamwstatic zfs_fuid_info_t *
228da6c28aamwzfs_replay_fuids(void *start, void **end, int idcnt, int domcnt, uint64_t uid,
229da6c28aamw    uint64_t gid)
230da6c28aamw{
231da6c28aamw	uint64_t *log_fuid = (uint64_t *)start;
232da6c28aamw	zfs_fuid_info_t *fuid_infop;
233da6c28aamw	int i;
234da6c28aamw
235da6c28aamw	fuid_infop = zfs_fuid_info_alloc();
236da6c28aamw	fuid_infop->z_domain_cnt = domcnt;
237da6c28aamw
238da6c28aamw	fuid_infop->z_domain_table =
239da6c28aamw	    kmem_zalloc(domcnt * sizeof (char **), KM_SLEEP);
240