]>
Commit | Line | Data |
---|---|---|
34dc7c2f BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 | * or http://www.opensolaris.org/os/licensing. | |
10 | * See the License for the specific language governing permissions | |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | /* | |
572e2857 | 22 | * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. |
49d39798 | 23 | * Copyright (c) 2012 Cyril Plisko. All rights reserved. |
1e0457e7 | 24 | * Copyright (c) 2013, 2017 by Delphix. All rights reserved. |
34dc7c2f BB |
25 | */ |
26 | ||
34dc7c2f BB |
27 | #include <sys/types.h> |
28 | #include <sys/param.h> | |
34dc7c2f BB |
29 | #include <sys/sysmacros.h> |
30 | #include <sys/cmn_err.h> | |
31 | #include <sys/kmem.h> | |
32 | #include <sys/thread.h> | |
33 | #include <sys/file.h> | |
34 | #include <sys/fcntl.h> | |
35 | #include <sys/vfs.h> | |
36 | #include <sys/fs/zfs.h> | |
37 | #include <sys/zfs_znode.h> | |
38 | #include <sys/zfs_dir.h> | |
39 | #include <sys/zfs_acl.h> | |
40 | #include <sys/zfs_fuid.h> | |
5484965a | 41 | #include <sys/zfs_vnops.h> |
34dc7c2f BB |
42 | #include <sys/spa.h> |
43 | #include <sys/zil.h> | |
44 | #include <sys/byteorder.h> | |
45 | #include <sys/stat.h> | |
34dc7c2f BB |
46 | #include <sys/acl.h> |
47 | #include <sys/atomic.h> | |
48 | #include <sys/cred.h> | |
5484965a | 49 | #include <sys/zpl.h> |
34dc7c2f | 50 | |
ba434b18 MM |
51 | /* |
52 | * NB: FreeBSD expects to be able to do vnode locking in lookup and | |
53 | * hold the locks across all subsequent VOPs until vput is called. | |
54 | * This means that its zfs vnops routines can't do any internal locking. | |
55 | * In order to have the same contract as the Linux vnops there would | |
56 | * needed to be duplicate locked vnops. If the vnops were used more widely | |
57 | * in common code this would likely be preferable. However, currently | |
58 | * this is the only file where this is the case. | |
59 | */ | |
60 | ||
34dc7c2f BB |
61 | /* |
62 | * Functions to replay ZFS intent log (ZIL) records | |
63 | * The functions are called through a function vector (zfs_replay_vector) | |
64 | * which is indexed by the transaction type. | |
65 | */ | |
66 | ||
67 | static void | |
5484965a | 68 | zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode, |
e9aa730c | 69 | uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid) |
34dc7c2f | 70 | { |
5484965a BB |
71 | bzero(vap, sizeof (*vap)); |
72 | vap->va_mask = (uint_t)mask; | |
5484965a | 73 | vap->va_mode = mode; |
273730d5 | 74 | #if defined(__FreeBSD__) || defined(__APPLE__) |
3d91490f MM |
75 | vap->va_type = IFTOVT(mode); |
76 | #endif | |
5484965a BB |
77 | vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; |
78 | vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; | |
13a9a6f5 | 79 | vap->va_rdev = zfs_cmpldev(rdev); |
5484965a | 80 | vap->va_nodeid = nodeid; |
34dc7c2f BB |
81 | } |
82 | ||
83 | /* ARGSUSED */ | |
84 | static int | |
867959b5 | 85 | zfs_replay_error(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 86 | { |
2e528b49 | 87 | return (SET_ERROR(ENOTSUP)); |
34dc7c2f BB |
88 | } |
89 | ||
90 | static void | |
91 | zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) | |
92 | { | |
93 | xoptattr_t *xoap = NULL; | |
94 | uint64_t *attrs; | |
95 | uint64_t *crtime; | |
96 | uint32_t *bitmap; | |
97 | void *scanstamp; | |
98 | int i; | |
99 | ||
5484965a | 100 | xvap->xva_vattr.va_mask |= ATTR_XVATTR; |
34dc7c2f | 101 | if ((xoap = xva_getxoptattr(xvap)) == NULL) { |
5484965a | 102 | xvap->xva_vattr.va_mask &= ~ATTR_XVATTR; /* shouldn't happen */ |
34dc7c2f BB |
103 | return; |
104 | } | |
105 | ||
106 | ASSERT(lrattr->lr_attr_masksize == xvap->xva_mapsize); | |
107 | ||
108 | bitmap = &lrattr->lr_attr_bitmap; | |
109 | for (i = 0; i != lrattr->lr_attr_masksize; i++, bitmap++) | |
110 | xvap->xva_reqattrmap[i] = *bitmap; | |
111 | ||
112 | attrs = (uint64_t *)(lrattr + lrattr->lr_attr_masksize - 1); | |
113 | crtime = attrs + 1; | |
114 | scanstamp = (caddr_t)(crtime + 2); | |
115 | ||
116 | if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) | |
117 | xoap->xoa_hidden = ((*attrs & XAT0_HIDDEN) != 0); | |
118 | if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) | |
119 | xoap->xoa_system = ((*attrs & XAT0_SYSTEM) != 0); | |
120 | if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) | |
121 | xoap->xoa_archive = ((*attrs & XAT0_ARCHIVE) != 0); | |
122 | if (XVA_ISSET_REQ(xvap, XAT_READONLY)) | |
123 | xoap->xoa_readonly = ((*attrs & XAT0_READONLY) != 0); | |
124 | if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) | |
125 | xoap->xoa_immutable = ((*attrs & XAT0_IMMUTABLE) != 0); | |
126 | if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) | |
127 | xoap->xoa_nounlink = ((*attrs & XAT0_NOUNLINK) != 0); | |
128 | if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) | |
129 | xoap->xoa_appendonly = ((*attrs & XAT0_APPENDONLY) != 0); | |
130 | if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) | |
131 | xoap->xoa_nodump = ((*attrs & XAT0_NODUMP) != 0); | |
132 | if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) | |
133 | xoap->xoa_opaque = ((*attrs & XAT0_OPAQUE) != 0); | |
134 | if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) | |
135 | xoap->xoa_av_modified = ((*attrs & XAT0_AV_MODIFIED) != 0); | |
136 | if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) | |
137 | xoap->xoa_av_quarantined = | |
138 | ((*attrs & XAT0_AV_QUARANTINED) != 0); | |
139 | if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) | |
140 | ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime); | |
9c5167d1 NF |
141 | if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) { |
142 | ASSERT(!XVA_ISSET_REQ(xvap, XAT_PROJID)); | |
143 | ||
34dc7c2f | 144 | bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); |
9c5167d1 NF |
145 | } else if (XVA_ISSET_REQ(xvap, XAT_PROJID)) { |
146 | /* | |
147 | * XAT_PROJID and XAT_AV_SCANSTAMP will never be valid | |
148 | * at the same time, so we can share the same space. | |
149 | */ | |
150 | bcopy(scanstamp, &xoap->xoa_projid, sizeof (uint64_t)); | |
151 | } | |
428870ff BB |
152 | if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) |
153 | xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); | |
572e2857 BB |
154 | if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) |
155 | xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0); | |
156 | if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) | |
157 | xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); | |
9c5167d1 NF |
158 | if (XVA_ISSET_REQ(xvap, XAT_PROJINHERIT)) |
159 | xoap->xoa_projinherit = ((*attrs & XAT0_PROJINHERIT) != 0); | |
34dc7c2f BB |
160 | } |
161 | ||
162 | static int | |
163 | zfs_replay_domain_cnt(uint64_t uid, uint64_t gid) | |
164 | { | |
165 | uint64_t uid_idx; | |
166 | uint64_t gid_idx; | |
167 | int domcnt = 0; | |
168 | ||
169 | uid_idx = FUID_INDEX(uid); | |
170 | gid_idx = FUID_INDEX(gid); | |
171 | if (uid_idx) | |
172 | domcnt++; | |
173 | if (gid_idx > 0 && gid_idx != uid_idx) | |
174 | domcnt++; | |
175 | ||
176 | return (domcnt); | |
177 | } | |
178 | ||
179 | static void * | |
180 | zfs_replay_fuid_domain_common(zfs_fuid_info_t *fuid_infop, void *start, | |
181 | int domcnt) | |
182 | { | |
183 | int i; | |
184 | ||
185 | for (i = 0; i != domcnt; i++) { | |
186 | fuid_infop->z_domain_table[i] = start; | |
187 | start = (caddr_t)start + strlen(start) + 1; | |
188 | } | |
189 | ||
190 | return (start); | |
191 | } | |
192 | ||
193 | /* | |
194 | * Set the uid/gid in the fuid_info structure. | |
195 | */ | |
196 | static void | |
197 | zfs_replay_fuid_ugid(zfs_fuid_info_t *fuid_infop, uint64_t uid, uint64_t gid) | |
198 | { | |
199 | /* | |
200 | * If owner or group are log specific FUIDs then slurp up | |
201 | * domain information and build zfs_fuid_info_t | |
202 | */ | |
203 | if (IS_EPHEMERAL(uid)) | |
204 | fuid_infop->z_fuid_owner = uid; | |
205 | ||
206 | if (IS_EPHEMERAL(gid)) | |
207 | fuid_infop->z_fuid_group = gid; | |
208 | } | |
209 | ||
210 | /* | |
211 | * Load fuid domains into fuid_info_t | |
212 | */ | |
213 | static zfs_fuid_info_t * | |
214 | zfs_replay_fuid_domain(void *buf, void **end, uint64_t uid, uint64_t gid) | |
215 | { | |
216 | int domcnt; | |
217 | ||
218 | zfs_fuid_info_t *fuid_infop; | |
219 | ||
220 | fuid_infop = zfs_fuid_info_alloc(); | |
221 | ||
222 | domcnt = zfs_replay_domain_cnt(uid, gid); | |
223 | ||
224 | if (domcnt == 0) | |
225 | return (fuid_infop); | |
226 | ||
227 | fuid_infop->z_domain_table = | |
160987b5 | 228 | kmem_zalloc(domcnt * sizeof (char *), KM_SLEEP); |
34dc7c2f BB |
229 | |
230 | zfs_replay_fuid_ugid(fuid_infop, uid, gid); | |
231 | ||
232 | fuid_infop->z_domain_cnt = domcnt; | |
233 | *end = zfs_replay_fuid_domain_common(fuid_infop, buf, domcnt); | |
234 | return (fuid_infop); | |
235 | } | |
236 | ||
237 | /* | |
238 | * load zfs_fuid_t's and fuid_domains into fuid_info_t | |
239 | */ | |
240 | static zfs_fuid_info_t * | |
241 | zfs_replay_fuids(void *start, void **end, int idcnt, int domcnt, uint64_t uid, | |
242 | uint64_t gid) | |
243 | { | |
244 | uint64_t *log_fuid = (uint64_t *)start; | |
245 | zfs_fuid_info_t *fuid_infop; | |
246 | int i; | |
247 | ||
248 | fuid_infop = zfs_fuid_info_alloc(); | |
249 | fuid_infop->z_domain_cnt = domcnt; | |
250 | ||
251 | fuid_infop->z_domain_table = | |
160987b5 | 252 | kmem_zalloc(domcnt * sizeof (char *), KM_SLEEP); |
34dc7c2f BB |
253 | |
254 | for (i = 0; i != idcnt; i++) { | |
255 | zfs_fuid_t *zfuid; | |
256 | ||
257 | zfuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP); | |
258 | zfuid->z_logfuid = *log_fuid; | |
259 | zfuid->z_id = -1; | |
260 | zfuid->z_domidx = 0; | |
261 | list_insert_tail(&fuid_infop->z_fuids, zfuid); | |
262 | log_fuid++; | |
263 | } | |
264 | ||
265 | zfs_replay_fuid_ugid(fuid_infop, uid, gid); | |
266 | ||
267 | *end = zfs_replay_fuid_domain_common(fuid_infop, log_fuid, domcnt); | |
268 | return (fuid_infop); | |
269 | } | |
270 | ||
271 | static void | |
272 | zfs_replay_swap_attrs(lr_attr_t *lrattr) | |
273 | { | |
274 | /* swap the lr_attr structure */ | |
275 | byteswap_uint32_array(lrattr, sizeof (*lrattr)); | |
276 | /* swap the bitmap */ | |
277 | byteswap_uint32_array(lrattr + 1, (lrattr->lr_attr_masksize - 1) * | |
278 | sizeof (uint32_t)); | |
279 | /* swap the attributes, create time + 64 bit word for attributes */ | |
280 | byteswap_uint64_array((caddr_t)(lrattr + 1) + (sizeof (uint32_t) * | |
281 | (lrattr->lr_attr_masksize - 1)), 3 * sizeof (uint64_t)); | |
282 | } | |
283 | ||
284 | /* | |
285 | * Replay file create with optional ACL, xvattr information as well | |
286 | * as option FUID information. | |
287 | */ | |
288 | static int | |
867959b5 | 289 | zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 290 | { |
867959b5 BB |
291 | zfsvfs_t *zfsvfs = arg1; |
292 | lr_acl_create_t *lracl = arg2; | |
34dc7c2f BB |
293 | char *name = NULL; /* location determined later */ |
294 | lr_create_t *lr = (lr_create_t *)lracl; | |
295 | znode_t *dzp; | |
657ce253 | 296 | znode_t *zp; |
34dc7c2f | 297 | xvattr_t xva; |
633e8030 | 298 | int vflg = 0; |
5484965a | 299 | vsecattr_t vsec = { 0 }; |
34dc7c2f BB |
300 | lr_attr_t *lrattr; |
301 | void *aclstart; | |
302 | void *fuidstart; | |
303 | size_t xvatlen = 0; | |
304 | uint64_t txtype; | |
50c957f7 NB |
305 | uint64_t objid; |
306 | uint64_t dnodesize; | |
34dc7c2f BB |
307 | int error; |
308 | ||
428870ff | 309 | txtype = (lr->lr_common.lrc_txtype & ~TX_CI); |
34dc7c2f BB |
310 | if (byteswap) { |
311 | byteswap_uint64_array(lracl, sizeof (*lracl)); | |
34dc7c2f BB |
312 | if (txtype == TX_CREATE_ACL_ATTR || |
313 | txtype == TX_MKDIR_ACL_ATTR) { | |
314 | lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); | |
315 | zfs_replay_swap_attrs(lrattr); | |
316 | xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); | |
317 | } | |
318 | ||
319 | aclstart = (caddr_t)(lracl + 1) + xvatlen; | |
320 | zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); | |
321 | /* swap fuids */ | |
322 | if (lracl->lr_fuidcnt) { | |
323 | byteswap_uint64_array((caddr_t)aclstart + | |
324 | ZIL_ACE_LENGTH(lracl->lr_acl_bytes), | |
325 | lracl->lr_fuidcnt * sizeof (uint64_t)); | |
326 | } | |
327 | } | |
328 | ||
0037b49e | 329 | if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) |
34dc7c2f BB |
330 | return (error); |
331 | ||
50c957f7 NB |
332 | objid = LR_FOID_GET_OBJ(lr->lr_foid); |
333 | dnodesize = LR_FOID_GET_SLOTS(lr->lr_foid) << DNODE_SHIFT; | |
334 | ||
34dc7c2f | 335 | xva_init(&xva); |
6742abf9 | 336 | zfs_init_vattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID, |
50c957f7 | 337 | lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, objid); |
34dc7c2f BB |
338 | |
339 | /* | |
340 | * All forms of zfs create (create, mkdir, mkxattrdir, symlink) | |
341 | * eventually end up in zfs_mknode(), which assigns the object's | |
50c957f7 NB |
342 | * creation time, generation number, and dnode size. The generic |
343 | * zfs_create() has no concept of these attributes, so we smuggle | |
344 | * the values inside the vattr's otherwise unused va_ctime, | |
345 | * va_nblocks, and va_fsid fields. | |
34dc7c2f BB |
346 | */ |
347 | ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); | |
348 | xva.xva_vattr.va_nblocks = lr->lr_gen; | |
50c957f7 | 349 | xva.xva_vattr.va_fsid = dnodesize; |
34dc7c2f | 350 | |
035e9611 CC |
351 | error = dnode_try_claim(zfsvfs->z_os, objid, dnodesize >> DNODE_SHIFT); |
352 | if (error) | |
34dc7c2f BB |
353 | goto bail; |
354 | ||
355 | if (lr->lr_common.lrc_txtype & TX_CI) | |
356 | vflg |= FIGNORECASE; | |
428870ff | 357 | switch (txtype) { |
34dc7c2f BB |
358 | case TX_CREATE_ACL: |
359 | aclstart = (caddr_t)(lracl + 1); | |
360 | fuidstart = (caddr_t)aclstart + | |
361 | ZIL_ACE_LENGTH(lracl->lr_acl_bytes); | |
0037b49e | 362 | zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, |
34dc7c2f BB |
363 | (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, |
364 | lr->lr_uid, lr->lr_gid); | |
6954c22f | 365 | fallthrough; |
34dc7c2f BB |
366 | case TX_CREATE_ACL_ATTR: |
367 | if (name == NULL) { | |
368 | lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); | |
369 | xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); | |
5484965a | 370 | xva.xva_vattr.va_mask |= ATTR_XVATTR; |
34dc7c2f BB |
371 | zfs_replay_xvattr(lrattr, &xva); |
372 | } | |
373 | vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; | |
374 | vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; | |
375 | vsec.vsa_aclcnt = lracl->lr_aclcnt; | |
376 | vsec.vsa_aclentsz = lracl->lr_acl_bytes; | |
377 | vsec.vsa_aclflags = lracl->lr_acl_flags; | |
0037b49e | 378 | if (zfsvfs->z_fuid_replay == NULL) { |
34dc7c2f BB |
379 | fuidstart = (caddr_t)(lracl + 1) + xvatlen + |
380 | ZIL_ACE_LENGTH(lracl->lr_acl_bytes); | |
0037b49e | 381 | zfsvfs->z_fuid_replay = |
34dc7c2f BB |
382 | zfs_replay_fuids(fuidstart, |
383 | (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, | |
384 | lr->lr_uid, lr->lr_gid); | |
385 | } | |
386 | ||
657ce253 MM |
387 | error = zfs_create(dzp, name, &xva.xva_vattr, |
388 | 0, 0, &zp, kcred, vflg, &vsec); | |
34dc7c2f BB |
389 | break; |
390 | case TX_MKDIR_ACL: | |
391 | aclstart = (caddr_t)(lracl + 1); | |
392 | fuidstart = (caddr_t)aclstart + | |
393 | ZIL_ACE_LENGTH(lracl->lr_acl_bytes); | |
0037b49e | 394 | zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, |
34dc7c2f BB |
395 | (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, |
396 | lr->lr_uid, lr->lr_gid); | |
6954c22f | 397 | fallthrough; |
34dc7c2f BB |
398 | case TX_MKDIR_ACL_ATTR: |
399 | if (name == NULL) { | |
400 | lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); | |
401 | xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); | |
402 | zfs_replay_xvattr(lrattr, &xva); | |
403 | } | |
404 | vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; | |
405 | vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; | |
406 | vsec.vsa_aclcnt = lracl->lr_aclcnt; | |
407 | vsec.vsa_aclentsz = lracl->lr_acl_bytes; | |
408 | vsec.vsa_aclflags = lracl->lr_acl_flags; | |
0037b49e | 409 | if (zfsvfs->z_fuid_replay == NULL) { |
34dc7c2f BB |
410 | fuidstart = (caddr_t)(lracl + 1) + xvatlen + |
411 | ZIL_ACE_LENGTH(lracl->lr_acl_bytes); | |
0037b49e | 412 | zfsvfs->z_fuid_replay = |
34dc7c2f BB |
413 | zfs_replay_fuids(fuidstart, |
414 | (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, | |
415 | lr->lr_uid, lr->lr_gid); | |
416 | } | |
657ce253 MM |
417 | error = zfs_mkdir(dzp, name, &xva.xva_vattr, |
418 | &zp, kcred, vflg, &vsec); | |
34dc7c2f BB |
419 | break; |
420 | default: | |
2e528b49 | 421 | error = SET_ERROR(ENOTSUP); |
34dc7c2f BB |
422 | } |
423 | ||
424 | bail: | |
3d91490f MM |
425 | if (error == 0 && zp != NULL) { |
426 | #ifdef __FreeBSD__ | |
427 | VOP_UNLOCK1(ZTOV(zp)); | |
428 | #endif | |
657ce253 | 429 | zrele(zp); |
3d91490f | 430 | } |
657ce253 | 431 | zrele(dzp); |
34dc7c2f | 432 | |
0037b49e BB |
433 | if (zfsvfs->z_fuid_replay) |
434 | zfs_fuid_info_free(zfsvfs->z_fuid_replay); | |
435 | zfsvfs->z_fuid_replay = NULL; | |
34dc7c2f BB |
436 | |
437 | return (error); | |
438 | } | |
439 | ||
440 | static int | |
867959b5 | 441 | zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 442 | { |
867959b5 BB |
443 | zfsvfs_t *zfsvfs = arg1; |
444 | lr_create_t *lr = arg2; | |
34dc7c2f BB |
445 | char *name = NULL; /* location determined later */ |
446 | char *link; /* symlink content follows name */ | |
447 | znode_t *dzp; | |
657ce253 | 448 | znode_t *zp = NULL; |
34dc7c2f BB |
449 | xvattr_t xva; |
450 | int vflg = 0; | |
451 | size_t lrsize = sizeof (lr_create_t); | |
452 | lr_attr_t *lrattr; | |
633e8030 | 453 | void *start; |
5484965a | 454 | size_t xvatlen; |
34dc7c2f | 455 | uint64_t txtype; |
50c957f7 NB |
456 | uint64_t objid; |
457 | uint64_t dnodesize; | |
34dc7c2f BB |
458 | int error; |
459 | ||
428870ff | 460 | txtype = (lr->lr_common.lrc_txtype & ~TX_CI); |
34dc7c2f BB |
461 | if (byteswap) { |
462 | byteswap_uint64_array(lr, sizeof (*lr)); | |
34dc7c2f BB |
463 | if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) |
464 | zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); | |
465 | } | |
466 | ||
467 | ||
0037b49e | 468 | if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) |
34dc7c2f BB |
469 | return (error); |
470 | ||
50c957f7 NB |
471 | objid = LR_FOID_GET_OBJ(lr->lr_foid); |
472 | dnodesize = LR_FOID_GET_SLOTS(lr->lr_foid) << DNODE_SHIFT; | |
473 | ||
34dc7c2f | 474 | xva_init(&xva); |
6742abf9 | 475 | zfs_init_vattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID, |
50c957f7 | 476 | lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, objid); |
34dc7c2f BB |
477 | |
478 | /* | |
479 | * All forms of zfs create (create, mkdir, mkxattrdir, symlink) | |
480 | * eventually end up in zfs_mknode(), which assigns the object's | |
50c957f7 NB |
481 | * creation time, generation number, and dnode slot count. The |
482 | * generic zfs_create() has no concept of these attributes, so | |
1e0457e7 MA |
483 | * we smuggle the values inside the vattr's otherwise unused |
484 | * va_ctime, va_nblocks, and va_fsid fields. | |
34dc7c2f BB |
485 | */ |
486 | ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); | |
487 | xva.xva_vattr.va_nblocks = lr->lr_gen; | |
50c957f7 | 488 | xva.xva_vattr.va_fsid = dnodesize; |
34dc7c2f | 489 | |
035e9611 CC |
490 | error = dnode_try_claim(zfsvfs->z_os, objid, dnodesize >> DNODE_SHIFT); |
491 | if (error) | |
34dc7c2f BB |
492 | goto out; |
493 | ||
494 | if (lr->lr_common.lrc_txtype & TX_CI) | |
495 | vflg |= FIGNORECASE; | |
496 | ||
497 | /* | |
498 | * Symlinks don't have fuid info, and CIFS never creates | |
499 | * symlinks. | |
500 | * | |
501 | * The _ATTR versions will grab the fuid info in their subcases. | |
502 | */ | |
503 | if ((int)lr->lr_common.lrc_txtype != TX_SYMLINK && | |
504 | (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR && | |
505 | (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) { | |
506 | start = (lr + 1); | |
0037b49e | 507 | zfsvfs->z_fuid_replay = |
34dc7c2f BB |
508 | zfs_replay_fuid_domain(start, &start, |
509 | lr->lr_uid, lr->lr_gid); | |
510 | } | |
511 | ||
428870ff | 512 | switch (txtype) { |
34dc7c2f BB |
513 | case TX_CREATE_ATTR: |
514 | lrattr = (lr_attr_t *)(caddr_t)(lr + 1); | |
515 | xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); | |
516 | zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); | |
517 | start = (caddr_t)(lr + 1) + xvatlen; | |
0037b49e | 518 | zfsvfs->z_fuid_replay = |
34dc7c2f BB |
519 | zfs_replay_fuid_domain(start, &start, |
520 | lr->lr_uid, lr->lr_gid); | |
521 | name = (char *)start; | |
6954c22f | 522 | fallthrough; |
34dc7c2f | 523 | |
34dc7c2f BB |
524 | case TX_CREATE: |
525 | if (name == NULL) | |
526 | name = (char *)start; | |
527 | ||
657ce253 MM |
528 | error = zfs_create(dzp, name, &xva.xva_vattr, |
529 | 0, 0, &zp, kcred, vflg, NULL); | |
34dc7c2f BB |
530 | break; |
531 | case TX_MKDIR_ATTR: | |
532 | lrattr = (lr_attr_t *)(caddr_t)(lr + 1); | |
533 | xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); | |
534 | zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); | |
535 | start = (caddr_t)(lr + 1) + xvatlen; | |
0037b49e | 536 | zfsvfs->z_fuid_replay = |
34dc7c2f BB |
537 | zfs_replay_fuid_domain(start, &start, |
538 | lr->lr_uid, lr->lr_gid); | |
539 | name = (char *)start; | |
6954c22f | 540 | fallthrough; |
34dc7c2f | 541 | |
34dc7c2f BB |
542 | case TX_MKDIR: |
543 | if (name == NULL) | |
544 | name = (char *)(lr + 1); | |
545 | ||
657ce253 MM |
546 | error = zfs_mkdir(dzp, name, &xva.xva_vattr, |
547 | &zp, kcred, vflg, NULL); | |
34dc7c2f BB |
548 | break; |
549 | case TX_MKXATTR: | |
657ce253 | 550 | error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); |
34dc7c2f BB |
551 | break; |
552 | case TX_SYMLINK: | |
553 | name = (char *)(lr + 1); | |
554 | link = name + strlen(name) + 1; | |
657ce253 MM |
555 | error = zfs_symlink(dzp, name, &xva.xva_vattr, |
556 | link, &zp, kcred, vflg); | |
34dc7c2f BB |
557 | break; |
558 | default: | |
2e528b49 | 559 | error = SET_ERROR(ENOTSUP); |
34dc7c2f BB |
560 | } |
561 | ||
3d91490f MM |
562 | out: |
563 | if (error == 0 && zp != NULL) { | |
13a9a6f5 | 564 | #ifdef __FreeBSD__ |
3d91490f | 565 | VOP_UNLOCK1(ZTOV(zp)); |
13a9a6f5 | 566 | #endif |
657ce253 | 567 | zrele(zp); |
3d91490f | 568 | } |
657ce253 | 569 | zrele(dzp); |
34dc7c2f | 570 | |
0037b49e BB |
571 | if (zfsvfs->z_fuid_replay) |
572 | zfs_fuid_info_free(zfsvfs->z_fuid_replay); | |
573 | zfsvfs->z_fuid_replay = NULL; | |
34dc7c2f BB |
574 | return (error); |
575 | } | |
576 | ||
577 | static int | |
867959b5 | 578 | zfs_replay_remove(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 579 | { |
867959b5 BB |
580 | zfsvfs_t *zfsvfs = arg1; |
581 | lr_remove_t *lr = arg2; | |
34dc7c2f BB |
582 | char *name = (char *)(lr + 1); /* name follows lr_remove_t */ |
583 | znode_t *dzp; | |
584 | int error; | |
585 | int vflg = 0; | |
586 | ||
587 | if (byteswap) | |
588 | byteswap_uint64_array(lr, sizeof (*lr)); | |
589 | ||
0037b49e | 590 | if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) |
34dc7c2f BB |
591 | return (error); |
592 | ||
593 | if (lr->lr_common.lrc_txtype & TX_CI) | |
594 | vflg |= FIGNORECASE; | |
595 | ||
596 | switch ((int)lr->lr_common.lrc_txtype) { | |
597 | case TX_REMOVE: | |
657ce253 | 598 | error = zfs_remove(dzp, name, kcred, vflg); |
34dc7c2f BB |
599 | break; |
600 | case TX_RMDIR: | |
657ce253 | 601 | error = zfs_rmdir(dzp, name, NULL, kcred, vflg); |
34dc7c2f BB |
602 | break; |
603 | default: | |
2e528b49 | 604 | error = SET_ERROR(ENOTSUP); |
34dc7c2f BB |
605 | } |
606 | ||
657ce253 | 607 | zrele(dzp); |
34dc7c2f BB |
608 | |
609 | return (error); | |
610 | } | |
611 | ||
612 | static int | |
867959b5 | 613 | zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 614 | { |
867959b5 BB |
615 | zfsvfs_t *zfsvfs = arg1; |
616 | lr_link_t *lr = arg2; | |
34dc7c2f BB |
617 | char *name = (char *)(lr + 1); /* name follows lr_link_t */ |
618 | znode_t *dzp, *zp; | |
619 | int error; | |
5484965a | 620 | int vflg = 0; |
34dc7c2f BB |
621 | |
622 | if (byteswap) | |
623 | byteswap_uint64_array(lr, sizeof (*lr)); | |
624 | ||
0037b49e | 625 | if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0) |
34dc7c2f BB |
626 | return (error); |
627 | ||
0037b49e | 628 | if ((error = zfs_zget(zfsvfs, lr->lr_link_obj, &zp)) != 0) { |
657ce253 | 629 | zrele(dzp); |
34dc7c2f BB |
630 | return (error); |
631 | } | |
632 | ||
633 | if (lr->lr_common.lrc_txtype & TX_CI) | |
634 | vflg |= FIGNORECASE; | |
635 | ||
657ce253 | 636 | error = zfs_link(dzp, zp, name, kcred, vflg); |
657ce253 MM |
637 | zrele(zp); |
638 | zrele(dzp); | |
34dc7c2f BB |
639 | |
640 | return (error); | |
641 | } | |
642 | ||
643 | static int | |
867959b5 | 644 | zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 645 | { |
867959b5 BB |
646 | zfsvfs_t *zfsvfs = arg1; |
647 | lr_rename_t *lr = arg2; | |
34dc7c2f BB |
648 | char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ |
649 | char *tname = sname + strlen(sname) + 1; | |
650 | znode_t *sdzp, *tdzp; | |
651 | int error; | |
652 | int vflg = 0; | |
653 | ||
654 | if (byteswap) | |
655 | byteswap_uint64_array(lr, sizeof (*lr)); | |
656 | ||
0037b49e | 657 | if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0) |
34dc7c2f BB |
658 | return (error); |
659 | ||
0037b49e | 660 | if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) { |
657ce253 | 661 | zrele(sdzp); |
34dc7c2f BB |
662 | return (error); |
663 | } | |
664 | ||
665 | if (lr->lr_common.lrc_txtype & TX_CI) | |
666 | vflg |= FIGNORECASE; | |
667 | ||
657ce253 | 668 | error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg); |
34dc7c2f | 669 | |
657ce253 MM |
670 | zrele(tdzp); |
671 | zrele(sdzp); | |
34dc7c2f BB |
672 | return (error); |
673 | } | |
674 | ||
675 | static int | |
867959b5 | 676 | zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 677 | { |
867959b5 BB |
678 | zfsvfs_t *zfsvfs = arg1; |
679 | lr_write_t *lr = arg2; | |
34dc7c2f BB |
680 | char *data = (char *)(lr + 1); /* data follows lr_write_t */ |
681 | znode_t *zp; | |
13a9a6f5 | 682 | int error; |
572e2857 | 683 | uint64_t eod, offset, length; |
34dc7c2f BB |
684 | |
685 | if (byteswap) | |
686 | byteswap_uint64_array(lr, sizeof (*lr)); | |
687 | ||
0037b49e | 688 | if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { |
34dc7c2f BB |
689 | /* |
690 | * As we can log writes out of order, it's possible the | |
691 | * file has been removed. In this case just drop the write | |
692 | * and return success. | |
693 | */ | |
694 | if (error == ENOENT) | |
695 | error = 0; | |
696 | return (error); | |
697 | } | |
698 | ||
428870ff BB |
699 | offset = lr->lr_offset; |
700 | length = lr->lr_length; | |
572e2857 | 701 | eod = offset + length; /* end of data for this write */ |
428870ff | 702 | |
572e2857 BB |
703 | /* |
704 | * This may be a write from a dmu_sync() for a whole block, | |
705 | * and may extend beyond the current end of the file. | |
706 | * We can't just replay what was written for this TX_WRITE as | |
707 | * a future TX_WRITE2 may extend the eof and the data for that | |
708 | * write needs to be there. So we write the whole block and | |
709 | * reduce the eof. This needs to be done within the single dmu | |
710 | * transaction created within vn_rdwr -> zfs_write. So a possible | |
0037b49e | 711 | * new end of file is passed through in zfsvfs->z_replay_eof |
572e2857 BB |
712 | */ |
713 | ||
0037b49e | 714 | zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */ |
428870ff BB |
715 | |
716 | /* If it's a dmu_sync() block, write the whole block */ | |
717 | if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { | |
718 | uint64_t blocksize = BP_GET_LSIZE(&lr->lr_blkptr); | |
719 | if (length < blocksize) { | |
720 | offset -= offset % blocksize; | |
721 | length = blocksize; | |
722 | } | |
572e2857 | 723 | if (zp->z_size < eod) |
0037b49e | 724 | zfsvfs->z_replay_eof = eod; |
428870ff | 725 | } |
13a9a6f5 | 726 | error = zfs_write_simple(zp, data, length, offset, NULL); |
657ce253 | 727 | zrele(zp); |
0037b49e | 728 | zfsvfs->z_replay_eof = 0; /* safety */ |
428870ff BB |
729 | |
730 | return (error); | |
731 | } | |
732 | ||
733 | /* | |
734 | * TX_WRITE2 are only generated when dmu_sync() returns EALREADY | |
735 | * meaning the pool block is already being synced. So now that we always write | |
736 | * out full blocks, all we have to do is expand the eof if | |
737 | * the file is grown. | |
738 | */ | |
739 | static int | |
867959b5 | 740 | zfs_replay_write2(void *arg1, void *arg2, boolean_t byteswap) |
428870ff | 741 | { |
867959b5 BB |
742 | zfsvfs_t *zfsvfs = arg1; |
743 | lr_write_t *lr = arg2; | |
428870ff BB |
744 | znode_t *zp; |
745 | int error; | |
746 | uint64_t end; | |
747 | ||
748 | if (byteswap) | |
749 | byteswap_uint64_array(lr, sizeof (*lr)); | |
750 | ||
0037b49e | 751 | if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) |
428870ff BB |
752 | return (error); |
753 | ||
572e2857 | 754 | top: |
428870ff BB |
755 | end = lr->lr_offset + lr->lr_length; |
756 | if (end > zp->z_size) { | |
0037b49e | 757 | dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); |
572e2857 | 758 | |
428870ff | 759 | zp->z_size = end; |
572e2857 BB |
760 | dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); |
761 | error = dmu_tx_assign(tx, TXG_WAIT); | |
762 | if (error) { | |
657ce253 | 763 | zrele(zp); |
572e2857 BB |
764 | if (error == ERESTART) { |
765 | dmu_tx_wait(tx); | |
766 | dmu_tx_abort(tx); | |
767 | goto top; | |
768 | } | |
769 | dmu_tx_abort(tx); | |
770 | return (error); | |
771 | } | |
0037b49e | 772 | (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs), |
572e2857 BB |
773 | (void *)&zp->z_size, sizeof (uint64_t), tx); |
774 | ||
775 | /* Ensure the replayed seq is updated */ | |
0037b49e | 776 | (void) zil_replaying(zfsvfs->z_log, tx); |
572e2857 BB |
777 | |
778 | dmu_tx_commit(tx); | |
428870ff | 779 | } |
34dc7c2f | 780 | |
657ce253 | 781 | zrele(zp); |
34dc7c2f BB |
782 | |
783 | return (error); | |
784 | } | |
785 | ||
786 | static int | |
867959b5 | 787 | zfs_replay_truncate(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 788 | { |
867959b5 BB |
789 | zfsvfs_t *zfsvfs = arg1; |
790 | lr_truncate_t *lr = arg2; | |
34dc7c2f BB |
791 | znode_t *zp; |
792 | flock64_t fl; | |
793 | int error; | |
794 | ||
795 | if (byteswap) | |
796 | byteswap_uint64_array(lr, sizeof (*lr)); | |
797 | ||
0037b49e | 798 | if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) |
34dc7c2f | 799 | return (error); |
34dc7c2f BB |
800 | |
801 | bzero(&fl, sizeof (fl)); | |
802 | fl.l_type = F_WRLCK; | |
126d0fa7 | 803 | fl.l_whence = SEEK_SET; |
34dc7c2f BB |
804 | fl.l_start = lr->lr_offset; |
805 | fl.l_len = lr->lr_length; | |
806 | ||
657ce253 | 807 | error = zfs_space(zp, F_FREESP, &fl, O_RDWR | O_LARGEFILE, |
633e8030 | 808 | lr->lr_offset, kcred); |
34dc7c2f | 809 | |
657ce253 | 810 | zrele(zp); |
34dc7c2f BB |
811 | |
812 | return (error); | |
813 | } | |
814 | ||
815 | static int | |
867959b5 | 816 | zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 817 | { |
867959b5 BB |
818 | zfsvfs_t *zfsvfs = arg1; |
819 | lr_setattr_t *lr = arg2; | |
34dc7c2f BB |
820 | znode_t *zp; |
821 | xvattr_t xva; | |
5484965a | 822 | vattr_t *vap = &xva.xva_vattr; |
34dc7c2f BB |
823 | int error; |
824 | void *start; | |
825 | ||
826 | xva_init(&xva); | |
827 | if (byteswap) { | |
828 | byteswap_uint64_array(lr, sizeof (*lr)); | |
829 | ||
5484965a | 830 | if ((lr->lr_mask & ATTR_XVATTR) && |
0037b49e | 831 | zfsvfs->z_version >= ZPL_VERSION_INITIAL) |
34dc7c2f BB |
832 | zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); |
833 | } | |
834 | ||
0037b49e | 835 | if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) |
34dc7c2f | 836 | return (error); |
34dc7c2f | 837 | |
5484965a BB |
838 | zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, |
839 | lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); | |
34dc7c2f | 840 | |
5484965a BB |
841 | vap->va_size = lr->lr_size; |
842 | ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); | |
843 | ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); | |
87f9371a NB |
844 | gethrestime(&vap->va_ctime); |
845 | vap->va_mask |= ATTR_CTIME; | |
34dc7c2f BB |
846 | |
847 | /* | |
848 | * Fill in xvattr_t portions if necessary. | |
849 | */ | |
850 | ||
851 | start = (lr_setattr_t *)(lr + 1); | |
5484965a | 852 | if (vap->va_mask & ATTR_XVATTR) { |
34dc7c2f BB |
853 | zfs_replay_xvattr((lr_attr_t *)start, &xva); |
854 | start = (caddr_t)start + | |
855 | ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); | |
856 | } else | |
5484965a | 857 | xva.xva_vattr.va_mask &= ~ATTR_XVATTR; |
34dc7c2f | 858 | |
0037b49e | 859 | zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, |
34dc7c2f BB |
860 | lr->lr_uid, lr->lr_gid); |
861 | ||
657ce253 | 862 | error = zfs_setattr(zp, vap, 0, kcred); |
34dc7c2f | 863 | |
0037b49e BB |
864 | zfs_fuid_info_free(zfsvfs->z_fuid_replay); |
865 | zfsvfs->z_fuid_replay = NULL; | |
657ce253 | 866 | zrele(zp); |
34dc7c2f BB |
867 | |
868 | return (error); | |
869 | } | |
870 | ||
871 | static int | |
867959b5 | 872 | zfs_replay_acl_v0(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 873 | { |
867959b5 BB |
874 | zfsvfs_t *zfsvfs = arg1; |
875 | lr_acl_v0_t *lr = arg2; | |
34dc7c2f BB |
876 | ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */ |
877 | vsecattr_t vsa; | |
878 | znode_t *zp; | |
879 | int error; | |
880 | ||
881 | if (byteswap) { | |
882 | byteswap_uint64_array(lr, sizeof (*lr)); | |
883 | zfs_oldace_byteswap(ace, lr->lr_aclcnt); | |
884 | } | |
885 | ||
0037b49e | 886 | if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) |
34dc7c2f | 887 | return (error); |
34dc7c2f BB |
888 | |
889 | bzero(&vsa, sizeof (vsa)); | |
890 | vsa.vsa_mask = VSA_ACE | VSA_ACECNT; | |
891 | vsa.vsa_aclcnt = lr->lr_aclcnt; | |
b128c09f BB |
892 | vsa.vsa_aclentsz = sizeof (ace_t) * vsa.vsa_aclcnt; |
893 | vsa.vsa_aclflags = 0; | |
34dc7c2f BB |
894 | vsa.vsa_aclentp = ace; |
895 | ||
657ce253 | 896 | error = zfs_setsecattr(zp, &vsa, 0, kcred); |
34dc7c2f | 897 | |
657ce253 | 898 | zrele(zp); |
34dc7c2f BB |
899 | |
900 | return (error); | |
901 | } | |
902 | ||
903 | /* | |
904 | * Replaying ACLs is complicated by FUID support. | |
905 | * The log record may contain some optional data | |
906 | * to be used for replaying FUID's. These pieces | |
907 | * are the actual FUIDs that were created initially. | |
908 | * The FUID table index may no longer be valid and | |
909 | * during zfs_create() a new index may be assigned. | |
910 | * Because of this the log will contain the original | |
4e33ba4c | 911 | * domain+rid in order to create a new FUID. |
34dc7c2f BB |
912 | * |
913 | * The individual ACEs may contain an ephemeral uid/gid which is no | |
914 | * longer valid and will need to be replaced with an actual FUID. | |
915 | * | |
916 | */ | |
917 | static int | |
867959b5 | 918 | zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap) |
34dc7c2f | 919 | { |
867959b5 BB |
920 | zfsvfs_t *zfsvfs = arg1; |
921 | lr_acl_t *lr = arg2; | |
34dc7c2f BB |
922 | ace_t *ace = (ace_t *)(lr + 1); |
923 | vsecattr_t vsa; | |
924 | znode_t *zp; | |
925 | int error; | |
926 | ||
927 | if (byteswap) { | |
928 | byteswap_uint64_array(lr, sizeof (*lr)); | |
929 | zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE); | |
930 | if (lr->lr_fuidcnt) { | |
931 | byteswap_uint64_array((caddr_t)ace + | |
932 | ZIL_ACE_LENGTH(lr->lr_acl_bytes), | |
933 | lr->lr_fuidcnt * sizeof (uint64_t)); | |
934 | } | |
935 | } | |
936 | ||
0037b49e | 937 | if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) |
34dc7c2f | 938 | return (error); |
34dc7c2f BB |
939 | |
940 | bzero(&vsa, sizeof (vsa)); | |
941 | vsa.vsa_mask = VSA_ACE | VSA_ACECNT | VSA_ACE_ACLFLAGS; | |
942 | vsa.vsa_aclcnt = lr->lr_aclcnt; | |
943 | vsa.vsa_aclentp = ace; | |
944 | vsa.vsa_aclentsz = lr->lr_acl_bytes; | |
945 | vsa.vsa_aclflags = lr->lr_acl_flags; | |
946 | ||
947 | if (lr->lr_fuidcnt) { | |
948 | void *fuidstart = (caddr_t)ace + | |
949 | ZIL_ACE_LENGTH(lr->lr_acl_bytes); | |
950 | ||
0037b49e | 951 | zfsvfs->z_fuid_replay = |
34dc7c2f BB |
952 | zfs_replay_fuids(fuidstart, &fuidstart, |
953 | lr->lr_fuidcnt, lr->lr_domcnt, 0, 0); | |
954 | } | |
955 | ||
657ce253 | 956 | error = zfs_setsecattr(zp, &vsa, 0, kcred); |
34dc7c2f | 957 | |
0037b49e BB |
958 | if (zfsvfs->z_fuid_replay) |
959 | zfs_fuid_info_free(zfsvfs->z_fuid_replay); | |
34dc7c2f | 960 | |
0037b49e | 961 | zfsvfs->z_fuid_replay = NULL; |
657ce253 | 962 | zrele(zp); |
34dc7c2f BB |
963 | |
964 | return (error); | |
965 | } | |
966 | ||
967 | /* | |
968 | * Callback vectors for replaying records | |
969 | */ | |
18168da7 | 970 | zil_replay_func_t *const zfs_replay_vector[TX_MAX_TYPE] = { |
867959b5 BB |
971 | zfs_replay_error, /* no such type */ |
972 | zfs_replay_create, /* TX_CREATE */ | |
973 | zfs_replay_create, /* TX_MKDIR */ | |
974 | zfs_replay_create, /* TX_MKXATTR */ | |
975 | zfs_replay_create, /* TX_SYMLINK */ | |
976 | zfs_replay_remove, /* TX_REMOVE */ | |
977 | zfs_replay_remove, /* TX_RMDIR */ | |
978 | zfs_replay_link, /* TX_LINK */ | |
979 | zfs_replay_rename, /* TX_RENAME */ | |
980 | zfs_replay_write, /* TX_WRITE */ | |
981 | zfs_replay_truncate, /* TX_TRUNCATE */ | |
982 | zfs_replay_setattr, /* TX_SETATTR */ | |
983 | zfs_replay_acl_v0, /* TX_ACL_V0 */ | |
984 | zfs_replay_acl, /* TX_ACL */ | |
985 | zfs_replay_create_acl, /* TX_CREATE_ACL */ | |
986 | zfs_replay_create, /* TX_CREATE_ATTR */ | |
987 | zfs_replay_create_acl, /* TX_CREATE_ACL_ATTR */ | |
988 | zfs_replay_create_acl, /* TX_MKDIR_ACL */ | |
989 | zfs_replay_create, /* TX_MKDIR_ATTR */ | |
990 | zfs_replay_create_acl, /* TX_MKDIR_ACL_ATTR */ | |
991 | zfs_replay_write2, /* TX_WRITE2 */ | |
34dc7c2f | 992 | }; |