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