Deleted Added
sdiff udiff text old ( 185321 ) new ( 209962 )
full compact
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#include <sys/types.h>
27#include <sys/param.h>
28#include <sys/systm.h>
29#include <sys/sysmacros.h>
30#include <sys/cmn_err.h>
31#include <sys/kmem.h>
32#include <sys/file.h>
33#include <sys/vfs.h>
34#include <sys/zfs_znode.h>
35#include <sys/zfs_dir.h>
36#include <sys/zil.h>
37#include <sys/zil_impl.h>
38#include <sys/byteorder.h>
39#include <sys/policy.h>
40#include <sys/stat.h>
41#include <sys/acl.h>
42#include <sys/dmu.h>
43#include <sys/spa.h>
44#include <sys/zfs_fuid.h>
45
46/*
47 * All the functions in this file are used to construct the log entries
48 * to record transactions. They allocate * an intent log transaction
49 * structure (itx_t) and save within it all the information necessary to
50 * possibly replay the transaction. The itx is then assigned a sequence
51 * number and inserted in the in-memory list anchored in the zilog.
52 */
53
54int
55zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap)
56{
57 int isxvattr = (vap->va_mask & AT_XVATTR);
58 switch (type) {
59 case Z_FILE:
60 if (vsecp == NULL && !isxvattr)
61 return (TX_CREATE);
62 if (vsecp && isxvattr)
63#ifdef TODO
64 return (TX_CREATE_ACL_ATTR);
65#else
66 panic("%s:%u: unsupported condition", __func__, __LINE__);
67#endif
68 if (vsecp)
69 return (TX_CREATE_ACL);
70 else
71 return (TX_CREATE_ATTR);
72 /*NOTREACHED*/
73 case Z_DIR:
74 if (vsecp == NULL && !isxvattr)
75 return (TX_MKDIR);
76 if (vsecp && isxvattr)
77#ifdef TODO
78 return (TX_MKDIR_ACL_ATTR);
79#else
80 panic("%s:%u: unsupported condition", __func__, __LINE__);
81#endif
82 if (vsecp)
83 return (TX_MKDIR_ACL);
84 else
85 return (TX_MKDIR_ATTR);
86 case Z_XATTRDIR:
87 return (TX_MKXATTR);
88 }
89 ASSERT(0);
90 return (TX_MAX_TYPE);
91}
92
93/*
94 * build up the log data necessary for logging xvattr_t
95 * First lr_attr_t is initialized. following the lr_attr_t
96 * is the mapsize and attribute bitmap copied from the xvattr_t.
97 * Following the bitmap and bitmapsize two 64 bit words are reserved
98 * for the create time which may be set. Following the create time
99 * records a single 64 bit integer which has the bits to set on
100 * replay for the xvattr.
101 */
102static void
103zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
104{
105 uint32_t *bitmap;
106 uint64_t *attrs;
107 uint64_t *crtime;
108 xoptattr_t *xoap;
109 void *scanstamp;
110 int i;
111
112 xoap = xva_getxoptattr(xvap);
113 ASSERT(xoap);
114
115 lrattr->lr_attr_masksize = xvap->xva_mapsize;
116 bitmap = &lrattr->lr_attr_bitmap;
117 for (i = 0; i != xvap->xva_mapsize; i++, bitmap++) {
118 *bitmap = xvap->xva_reqattrmap[i];
119 }
120
121 /* Now pack the attributes up in a single uint64_t */
122 attrs = (uint64_t *)bitmap;
123 crtime = attrs + 1;
124 scanstamp = (caddr_t)(crtime + 2);
125 *attrs = 0;
126 if (XVA_ISSET_REQ(xvap, XAT_READONLY))
127 *attrs |= (xoap->xoa_readonly == 0) ? 0 :
128 XAT0_READONLY;
129 if (XVA_ISSET_REQ(xvap, XAT_HIDDEN))
130 *attrs |= (xoap->xoa_hidden == 0) ? 0 :
131 XAT0_HIDDEN;
132 if (XVA_ISSET_REQ(xvap, XAT_SYSTEM))
133 *attrs |= (xoap->xoa_system == 0) ? 0 :
134 XAT0_SYSTEM;
135 if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE))
136 *attrs |= (xoap->xoa_archive == 0) ? 0 :
137 XAT0_ARCHIVE;
138 if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE))
139 *attrs |= (xoap->xoa_immutable == 0) ? 0 :
140 XAT0_IMMUTABLE;
141 if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK))
142 *attrs |= (xoap->xoa_nounlink == 0) ? 0 :
143 XAT0_NOUNLINK;
144 if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY))
145 *attrs |= (xoap->xoa_appendonly == 0) ? 0 :
146 XAT0_APPENDONLY;
147 if (XVA_ISSET_REQ(xvap, XAT_OPAQUE))
148 *attrs |= (xoap->xoa_opaque == 0) ? 0 :
149 XAT0_APPENDONLY;
150 if (XVA_ISSET_REQ(xvap, XAT_NODUMP))
151 *attrs |= (xoap->xoa_nodump == 0) ? 0 :
152 XAT0_NODUMP;
153 if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED))
154 *attrs |= (xoap->xoa_av_quarantined == 0) ? 0 :
155 XAT0_AV_QUARANTINED;
156 if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED))
157 *attrs |= (xoap->xoa_av_modified == 0) ? 0 :
158 XAT0_AV_MODIFIED;
159 if (XVA_ISSET_REQ(xvap, XAT_CREATETIME))
160 ZFS_TIME_ENCODE(&xoap->xoa_createtime, crtime);
161 if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP))
162 bcopy(xoap->xoa_av_scanstamp, scanstamp, AV_SCANSTAMP_SZ);
163}
164
165static void *
166zfs_log_fuid_ids(zfs_fuid_info_t *fuidp, void *start)
167{
168 zfs_fuid_t *zfuid;
169 uint64_t *fuidloc = start;
170
171 /* First copy in the ACE FUIDs */
172 for (zfuid = list_head(&fuidp->z_fuids); zfuid;
173 zfuid = list_next(&fuidp->z_fuids, zfuid)) {
174 *fuidloc++ = zfuid->z_logfuid;
175 }
176 return (fuidloc);
177}
178
179
180static void *
181zfs_log_fuid_domains(zfs_fuid_info_t *fuidp, void *start)
182{
183 zfs_fuid_domain_t *zdomain;
184
185 /* now copy in the domain info, if any */
186 if (fuidp->z_domain_str_sz != 0) {
187 for (zdomain = list_head(&fuidp->z_domains); zdomain;
188 zdomain = list_next(&fuidp->z_domains, zdomain)) {
189 bcopy((void *)zdomain->z_domain, start,
190 strlen(zdomain->z_domain) + 1);
191 start = (caddr_t)start +
192 strlen(zdomain->z_domain) + 1;
193 }
194 }
195 return (start);
196}
197
198/*
199 * zfs_log_create() is used to handle TX_CREATE, TX_CREATE_ATTR, TX_MKDIR,
200 * TX_MKDIR_ATTR and TX_MKXATTR
201 * transactions.
202 *
203 * TX_CREATE and TX_MKDIR are standard creates, but they may have FUID
204 * domain information appended prior to the name. In this case the
205 * uid/gid in the log record will be a log centric FUID.
206 *
207 * TX_CREATE_ACL_ATTR and TX_MKDIR_ACL_ATTR handle special creates that
208 * may contain attributes, ACL and optional fuid information.
209 *
210 * TX_CREATE_ACL and TX_MKDIR_ACL handle special creates that specify
211 * and ACL and normal users/groups in the ACEs.
212 *
213 * There may be an optional xvattr attribute information similar
214 * to zfs_log_setattr.
215 *
216 * Also, after the file name "domain" strings may be appended.
217 */
218void
219zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
220 znode_t *dzp, znode_t *zp, char *name, vsecattr_t *vsecp,
221 zfs_fuid_info_t *fuidp, vattr_t *vap)
222{
223 itx_t *itx;
224 uint64_t seq;
225 lr_create_t *lr;
226 lr_acl_create_t *lracl;
227 size_t aclsize;
228 size_t xvatsize = 0;
229 size_t txsize;
230 xvattr_t *xvap = (xvattr_t *)vap;
231 void *end;
232 size_t lrsize;
233 size_t namesize = strlen(name) + 1;
234 size_t fuidsz = 0;
235
236 if (zilog == NULL)
237 return;
238
239 /*
240 * If we have FUIDs present then add in space for
241 * domains and ACE fuid's if any.
242 */
243 if (fuidp) {
244 fuidsz += fuidp->z_domain_str_sz;
245 fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t);
246 }
247
248 if (vap->va_mask & AT_XVATTR)
249 xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize);
250
251 if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR ||
252 (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR ||
253 (int)txtype == TX_MKXATTR) {
254 txsize = sizeof (*lr) + namesize + fuidsz + xvatsize;
255 lrsize = sizeof (*lr);
256 } else {
257 aclsize = (vsecp) ? vsecp->vsa_aclentsz : 0;
258 txsize =
259 sizeof (lr_acl_create_t) + namesize + fuidsz +
260 ZIL_ACE_LENGTH(aclsize) + xvatsize;
261 lrsize = sizeof (lr_acl_create_t);
262 }
263
264 itx = zil_itx_create(txtype, txsize);
265
266 lr = (lr_create_t *)&itx->itx_lr;
267 lr->lr_doid = dzp->z_id;
268 lr->lr_foid = zp->z_id;
269 lr->lr_mode = zp->z_phys->zp_mode;
270 if (!IS_EPHEMERAL(zp->z_phys->zp_uid)) {
271 lr->lr_uid = (uint64_t)zp->z_phys->zp_uid;
272 } else {
273 lr->lr_uid = fuidp->z_fuid_owner;
274 }
275 if (!IS_EPHEMERAL(zp->z_phys->zp_gid)) {
276 lr->lr_gid = (uint64_t)zp->z_phys->zp_gid;
277 } else {
278 lr->lr_gid = fuidp->z_fuid_group;
279 }
280 lr->lr_gen = zp->z_phys->zp_gen;
281 lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
282 lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
283 lr->lr_rdev = zp->z_phys->zp_rdev;
284
285 /*
286 * Fill in xvattr info if any
287 */
288 if (vap->va_mask & AT_XVATTR) {
289 zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap);
290 end = (caddr_t)lr + lrsize + xvatsize;
291 } else {
292 end = (caddr_t)lr + lrsize;
293 }
294
295 /* Now fill in any ACL info */
296
297 if (vsecp) {
298 lracl = (lr_acl_create_t *)&itx->itx_lr;
299 lracl->lr_aclcnt = vsecp->vsa_aclcnt;
300 lracl->lr_acl_bytes = aclsize;
301 lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
302 lracl->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0;
303 if (vsecp->vsa_aclflags & VSA_ACE_ACLFLAGS)
304 lracl->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags;
305 else
306 lracl->lr_acl_flags = 0;
307
308 bcopy(vsecp->vsa_aclentp, end, aclsize);
309 end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize);
310 }
311
312 /* drop in FUID info */
313 if (fuidp) {
314 end = zfs_log_fuid_ids(fuidp, end);
315 end = zfs_log_fuid_domains(fuidp, end);
316 }
317 /*
318 * Now place file name in log record
319 */
320 bcopy(name, end, namesize);
321
322 seq = zil_itx_assign(zilog, itx, tx);
323 dzp->z_last_itx = seq;
324 zp->z_last_itx = seq;
325}
326
327/*
328 * zfs_log_remove() handles both TX_REMOVE and TX_RMDIR transactions.
329 */
330void
331zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
332 znode_t *dzp, char *name)
333{
334 itx_t *itx;
335 uint64_t seq;
336 lr_remove_t *lr;
337 size_t namesize = strlen(name) + 1;
338
339 if (zilog == NULL)
340 return;
341
342 itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
343 lr = (lr_remove_t *)&itx->itx_lr;
344 lr->lr_doid = dzp->z_id;
345 bcopy(name, (char *)(lr + 1), namesize);
346
347 seq = zil_itx_assign(zilog, itx, tx);
348 dzp->z_last_itx = seq;
349}
350
351/*
352 * zfs_log_link() handles TX_LINK transactions.
353 */
354void
355zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
356 znode_t *dzp, znode_t *zp, char *name)
357{
358 itx_t *itx;
359 uint64_t seq;
360 lr_link_t *lr;
361 size_t namesize = strlen(name) + 1;
362
363 if (zilog == NULL)
364 return;
365
366 itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
367 lr = (lr_link_t *)&itx->itx_lr;
368 lr->lr_doid = dzp->z_id;
369 lr->lr_link_obj = zp->z_id;
370 bcopy(name, (char *)(lr + 1), namesize);
371
372 seq = zil_itx_assign(zilog, itx, tx);
373 dzp->z_last_itx = seq;
374 zp->z_last_itx = seq;
375}
376
377/*
378 * zfs_log_symlink() handles TX_SYMLINK transactions.
379 */
380void
381zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
382 znode_t *dzp, znode_t *zp, char *name, char *link)
383{
384 itx_t *itx;
385 uint64_t seq;
386 lr_create_t *lr;
387 size_t namesize = strlen(name) + 1;
388 size_t linksize = strlen(link) + 1;
389
390 if (zilog == NULL)
391 return;
392
393 itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize);
394 lr = (lr_create_t *)&itx->itx_lr;
395 lr->lr_doid = dzp->z_id;
396 lr->lr_foid = zp->z_id;
397 lr->lr_mode = zp->z_phys->zp_mode;
398 lr->lr_uid = zp->z_phys->zp_uid;
399 lr->lr_gid = zp->z_phys->zp_gid;
400 lr->lr_gen = zp->z_phys->zp_gen;
401 lr->lr_crtime[0] = zp->z_phys->zp_crtime[0];
402 lr->lr_crtime[1] = zp->z_phys->zp_crtime[1];
403 bcopy(name, (char *)(lr + 1), namesize);
404 bcopy(link, (char *)(lr + 1) + namesize, linksize);
405
406 seq = zil_itx_assign(zilog, itx, tx);
407 dzp->z_last_itx = seq;
408 zp->z_last_itx = seq;
409}
410
411/*
412 * zfs_log_rename() handles TX_RENAME transactions.
413 */
414void
415zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
416 znode_t *sdzp, char *sname, znode_t *tdzp, char *dname, znode_t *szp)
417{
418 itx_t *itx;
419 uint64_t seq;
420 lr_rename_t *lr;
421 size_t snamesize = strlen(sname) + 1;
422 size_t dnamesize = strlen(dname) + 1;
423
424 if (zilog == NULL)
425 return;
426
427 itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
428 lr = (lr_rename_t *)&itx->itx_lr;
429 lr->lr_sdoid = sdzp->z_id;
430 lr->lr_tdoid = tdzp->z_id;
431 bcopy(sname, (char *)(lr + 1), snamesize);
432 bcopy(dname, (char *)(lr + 1) + snamesize, dnamesize);
433
434 seq = zil_itx_assign(zilog, itx, tx);
435 sdzp->z_last_itx = seq;
436 tdzp->z_last_itx = seq;
437 szp->z_last_itx = seq;
438}
439
440/*
441 * zfs_log_write() handles TX_WRITE transactions.
442 */
443ssize_t zfs_immediate_write_sz = 32768;
444
445#define ZIL_MAX_LOG_DATA (SPA_MAXBLOCKSIZE - sizeof (zil_trailer_t) - \
446 sizeof (lr_write_t))
447
448void
449zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
450 znode_t *zp, offset_t off, ssize_t resid, int ioflag)
451{
452 itx_wr_state_t write_state;
453 boolean_t slogging;
454 uintptr_t fsync_cnt;
455
456 if (zilog == NULL || zp->z_unlinked)
457 return;
458
459 /*
460 * Writes are handled in three different ways:
461 *
462 * WR_INDIRECT:
463 * In this mode, if we need to commit the write later, then the block
464 * is immediately written into the file system (using dmu_sync),
465 * and a pointer to the block is put into the log record.
466 * When the txg commits the block is linked in.
467 * This saves additionally writing the data into the log record.
468 * There are a few requirements for this to occur:
469 * - write is greater than zfs_immediate_write_sz
470 * - not using slogs (as slogs are assumed to always be faster
471 * than writing into the main pool)
472 * - the write occupies only one block
473 * WR_COPIED:
474 * If we know we'll immediately be committing the
475 * transaction (FSYNC or FDSYNC), the we allocate a larger
476 * log record here for the data and copy the data in.
477 * WR_NEED_COPY:
478 * Otherwise we don't allocate a buffer, and *if* we need to
479 * flush the write later then a buffer is allocated and
480 * we retrieve the data using the dmu.
481 */
482 slogging = spa_has_slogs(zilog->zl_spa);
483 if (resid > zfs_immediate_write_sz && !slogging && resid <= zp->z_blksz)
484 write_state = WR_INDIRECT;
485 else if (ioflag & (FSYNC | FDSYNC))
486 write_state = WR_COPIED;
487 else
488 write_state = WR_NEED_COPY;
489
490 if ((fsync_cnt = (uintptr_t)tsd_get(zfs_fsyncer_key)) != 0) {
491 (void) tsd_set(zfs_fsyncer_key, (void *)(fsync_cnt - 1));
492 }
493
494 while (resid) {
495 itx_t *itx;
496 lr_write_t *lr;
497 ssize_t len;
498
499 /*
500 * If the write would overflow the largest block then split it.
501 */
502 if (write_state != WR_INDIRECT && resid > ZIL_MAX_LOG_DATA)
503 len = SPA_MAXBLOCKSIZE >> 1;
504 else
505 len = resid;
506
507 itx = zil_itx_create(txtype, sizeof (*lr) +
508 (write_state == WR_COPIED ? len : 0));
509 lr = (lr_write_t *)&itx->itx_lr;
510 if (write_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os,
511 zp->z_id, off, len, lr + 1) != 0) {
512 kmem_free(itx, offsetof(itx_t, itx_lr) +
513 itx->itx_lr.lrc_reclen);
514 itx = zil_itx_create(txtype, sizeof (*lr));
515 lr = (lr_write_t *)&itx->itx_lr;
516 write_state = WR_NEED_COPY;
517 }
518
519 itx->itx_wr_state = write_state;
520 if (write_state == WR_NEED_COPY)
521 itx->itx_sod += len;
522 lr->lr_foid = zp->z_id;
523 lr->lr_offset = off;
524 lr->lr_length = len;
525 lr->lr_blkoff = 0;
526 BP_ZERO(&lr->lr_blkptr);
527
528 itx->itx_private = zp->z_zfsvfs;
529
530 if ((zp->z_sync_cnt != 0) || (fsync_cnt != 0) ||
531 (ioflag & (FSYNC | FDSYNC)))
532 itx->itx_sync = B_TRUE;
533 else
534 itx->itx_sync = B_FALSE;
535
536 zp->z_last_itx = zil_itx_assign(zilog, itx, tx);
537
538 off += len;
539 resid -= len;
540 }
541}
542
543/*
544 * zfs_log_truncate() handles TX_TRUNCATE transactions.
545 */
546void
547zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
548 znode_t *zp, uint64_t off, uint64_t len)
549{
550 itx_t *itx;
551 uint64_t seq;
552 lr_truncate_t *lr;
553
554 if (zilog == NULL || zp->z_unlinked)
555 return;
556
557 itx = zil_itx_create(txtype, sizeof (*lr));
558 lr = (lr_truncate_t *)&itx->itx_lr;
559 lr->lr_foid = zp->z_id;
560 lr->lr_offset = off;
561 lr->lr_length = len;
562
563 itx->itx_sync = (zp->z_sync_cnt != 0);
564 seq = zil_itx_assign(zilog, itx, tx);
565 zp->z_last_itx = seq;
566}
567
568/*
569 * zfs_log_setattr() handles TX_SETATTR transactions.
570 */
571void
572zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
573 znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp)
574{
575 itx_t *itx;
576 uint64_t seq;
577 lr_setattr_t *lr;
578 xvattr_t *xvap = (xvattr_t *)vap;
579 size_t recsize = sizeof (lr_setattr_t);
580 void *start;
581
582
583 if (zilog == NULL || zp->z_unlinked)
584 return;
585
586 /*
587 * If XVATTR set, then log record size needs to allow
588 * for lr_attr_t + xvattr mask, mapsize and create time
589 * plus actual attribute values
590 */
591 if (vap->va_mask & AT_XVATTR)
592 recsize = sizeof (*lr) + ZIL_XVAT_SIZE(xvap->xva_mapsize);
593
594 if (fuidp)
595 recsize += fuidp->z_domain_str_sz;
596
597 itx = zil_itx_create(txtype, recsize);
598 lr = (lr_setattr_t *)&itx->itx_lr;
599 lr->lr_foid = zp->z_id;
600 lr->lr_mask = (uint64_t)mask_applied;
601 lr->lr_mode = (uint64_t)vap->va_mode;
602 if ((mask_applied & AT_UID) && IS_EPHEMERAL(vap->va_uid))
603 lr->lr_uid = fuidp->z_fuid_owner;
604 else
605 lr->lr_uid = (uint64_t)vap->va_uid;
606
607 if ((mask_applied & AT_GID) && IS_EPHEMERAL(vap->va_gid))
608 lr->lr_gid = fuidp->z_fuid_group;
609 else
610 lr->lr_gid = (uint64_t)vap->va_gid;
611
612 lr->lr_size = (uint64_t)vap->va_size;
613 ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime);
614 ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime);
615 start = (lr_setattr_t *)(lr + 1);
616 if (vap->va_mask & AT_XVATTR) {
617 zfs_log_xvattr((lr_attr_t *)start, xvap);
618 start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize);
619 }
620
621 /*
622 * Now stick on domain information if any on end
623 */
624
625 if (fuidp)
626 (void) zfs_log_fuid_domains(fuidp, start);
627
628 itx->itx_sync = (zp->z_sync_cnt != 0);
629 seq = zil_itx_assign(zilog, itx, tx);
630 zp->z_last_itx = seq;
631}
632
633/*
634 * zfs_log_acl() handles TX_ACL transactions.
635 */
636void
637zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
638 vsecattr_t *vsecp, zfs_fuid_info_t *fuidp)
639{
640 itx_t *itx;
641 uint64_t seq;
642 lr_acl_v0_t *lrv0;
643 lr_acl_t *lr;
644 int txtype;
645 int lrsize;
646 size_t txsize;
647 size_t aclbytes = vsecp->vsa_aclentsz;
648
649 if (zilog == NULL || zp->z_unlinked)
650 return;
651
652 txtype = (zp->z_zfsvfs->z_version < ZPL_VERSION_FUID) ?
653 TX_ACL_V0 : TX_ACL;
654
655 if (txtype == TX_ACL)
656 lrsize = sizeof (*lr);
657 else
658 lrsize = sizeof (*lrv0);
659
660 txsize = lrsize +
661 ((txtype == TX_ACL) ? ZIL_ACE_LENGTH(aclbytes) : aclbytes) +
662 (fuidp ? fuidp->z_domain_str_sz : 0) +
663 sizeof (uint64_t) * (fuidp ? fuidp->z_fuid_cnt : 0);
664
665 itx = zil_itx_create(txtype, txsize);
666
667 lr = (lr_acl_t *)&itx->itx_lr;
668 lr->lr_foid = zp->z_id;
669 if (txtype == TX_ACL) {
670 lr->lr_acl_bytes = aclbytes;
671 lr->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
672 lr->lr_fuidcnt = fuidp ? fuidp->z_fuid_cnt : 0;
673 if (vsecp->vsa_mask & VSA_ACE_ACLFLAGS)
674 lr->lr_acl_flags = (uint64_t)vsecp->vsa_aclflags;
675 else
676 lr->lr_acl_flags = 0;
677 }
678 lr->lr_aclcnt = (uint64_t)vsecp->vsa_aclcnt;
679
680 if (txtype == TX_ACL_V0) {
681 lrv0 = (lr_acl_v0_t *)lr;
682 bcopy(vsecp->vsa_aclentp, (ace_t *)(lrv0 + 1), aclbytes);
683 } else {
684 void *start = (ace_t *)(lr + 1);
685
686 bcopy(vsecp->vsa_aclentp, start, aclbytes);
687
688 start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes);
689
690 if (fuidp) {
691 start = zfs_log_fuid_ids(fuidp, start);
692 (void) zfs_log_fuid_domains(fuidp, start);
693 }
694 }
695
696 itx->itx_sync = (zp->z_sync_cnt != 0);
697 seq = zil_itx_assign(zilog, itx, tx);
698 zp->z_last_itx = seq;
699}