Home | History | Annotate | Download | only in cachefs
      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 2007 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/param.h>
     29 #include <sys/types.h>
     30 #include <sys/systm.h>
     31 #include <sys/cred.h>
     32 #include <sys/proc.h>
     33 #include <sys/user.h>
     34 #include <sys/time.h>
     35 #include <sys/vnode.h>
     36 #include <sys/vfs.h>
     37 #include <sys/file.h>
     38 #include <sys/filio.h>
     39 #include <sys/uio.h>
     40 #include <sys/buf.h>
     41 #include <sys/mman.h>
     42 #include <sys/tiuser.h>
     43 #include <sys/pathname.h>
     44 #include <sys/dirent.h>
     45 #include <sys/conf.h>
     46 #include <sys/debug.h>
     47 #include <sys/vmsystm.h>
     48 #include <sys/fcntl.h>
     49 #include <sys/flock.h>
     50 #include <sys/swap.h>
     51 #include <sys/errno.h>
     52 #include <sys/sysmacros.h>
     53 #include <sys/disp.h>
     54 #include <sys/kmem.h>
     55 #include <sys/cmn_err.h>
     56 #include <sys/vtrace.h>
     57 #include <sys/mount.h>
     58 #include <sys/bootconf.h>
     59 #include <sys/dnlc.h>
     60 #include <sys/stat.h>
     61 
     62 #include <vm/hat.h>
     63 #include <vm/as.h>
     64 #include <vm/page.h>
     65 #include <vm/pvn.h>
     66 #include <vm/seg.h>
     67 #include <vm/seg_map.h>
     68 #include <vm/seg_vn.h>
     69 #include <vm/rm.h>
     70 #include <sys/fs/cachefs_fs.h>
     71 #include <sys/fs/cachefs_dlog.h>
     72 #include <fs/fs_subr.h>
     73 
     74 static int cachefs_dlog_mapreserve(fscache_t *fscp, int size);
     75 
     76 #ifdef _LP64
     77 
     78 static void cachefs_dlog_attrchk(vattr_t *vap, char *funcname);
     79 
     80 #define	CACHEFS_DLOG_TS_COPY(in_tsp, out_tsp, str, str1)		\
     81 	{								\
     82 		int	ovferr = 0;					\
     83 		CACHEFS_TS_TO_CFS_TS_COPY(in_tsp, out_tsp, ovferr);	\
     84 		if (ovferr)						\
     85 			cmn_err(CE_WARN, "%s%s overflow", str, str1);	\
     86 	}
     87 
     88 #define	CACHEFS_DLOG_DEV_COPY(in_dev, out_dev, str, str1)		\
     89 	{								\
     90 		int	ovferr = 0;					\
     91 		CACHEFS_DEV_TO_CFS_DEV_COPY(in_dev, out_dev, ovferr);	\
     92 		if (ovferr)						\
     93 			cmn_err(CE_WARN, "%s%s 0x%lx -> 0x%x overflow",	\
     94 				str, str1, in_dev, (dev32_t)(out_dev));	\
     95 	}
     96 
     97 #define	CACHEFS_DLOG_VATTR_COPY(in_vap, out_vap, str)			\
     98 	{								\
     99 		int	ovferr = 0;					\
    100 		CACHEFS_VATTR_TO_CFS_VATTR_COPY(in_vap, out_vap, ovferr); \
    101 		if (ovferr)						\
    102 			cachefs_dlog_attrchk(in_vap, str);		\
    103 	}
    104 
    105 /*
    106  * check attr error - if we get an overflow error copying vattr, make sure
    107  * the field affected is actually wanted, or it might be junk
    108  */
    109 static void
    110 cachefs_dlog_attrchk(vattr_t *vap, char *str)
    111 {
    112 	dev_t		tmpdev;
    113 	cfs_timestruc_t	ts;
    114 
    115 	if (vap->va_mask & AT_FSID) {
    116 		CACHEFS_DLOG_DEV_COPY(vap->va_fsid, tmpdev, str, ".va_fsid");
    117 	}
    118 	if (vap->va_mask & AT_RDEV) {
    119 		CACHEFS_DLOG_DEV_COPY(vap->va_rdev, tmpdev, str, ".va_rdev");
    120 	}
    121 	if (vap->va_mask & AT_MTIME) {
    122 		CACHEFS_DLOG_TS_COPY(&vap->va_mtime, &ts, str, ".va_mtime");
    123 	}
    124 	if (vap->va_mask & AT_ATIME) {
    125 		CACHEFS_DLOG_TS_COPY(&vap->va_atime, &ts, str, ".va_atime");
    126 	}
    127 	if (vap->va_mask & AT_CTIME) {
    128 		CACHEFS_DLOG_TS_COPY(&vap->va_ctime, &ts, str, ".va_ctime");
    129 	}
    130 }
    131 
    132 #else /* not _LP64 */
    133 
    134 #define	CACHEFS_DLOG_TS_COPY(in_tsp, out_tsp, str, str1)		\
    135 	CACHEFS_TS_TO_CFS_TS_COPY(in_tsp, out_tsp, error)
    136 
    137 #define	CACHEFS_DLOG_DEV_COPY(in_dev, out_dev, str, str1)		\
    138 	CACHEFS_DEV_TO_CFS_DEV_COPY(in_dev, out_dev, error)
    139 
    140 #define	CACHEFS_DLOG_VATTR_COPY(in_vap, out_vap, str)			\
    141 	CACHEFS_VATTR_TO_CFS_VATTR_COPY(in_vap, out_vap, error)
    142 
    143 #endif /* _LP64 */
    144 
    145 /*
    146  *
    147  * Cachefs used to know too much about how creds looked; since it's
    148  * committed to persistent storage, we can't change the layout so
    149  * it now has a "dl_cred_t" which (unsurprisingly) looks exactly like
    150  * an old credential.
    151  *
    152  * The dst argument needs to point to:
    153  *		struct dl_cred_t;
    154  *		<buffer space>			buffer for groups
    155  *
    156  * The source is a proper kernel cred_t.
    157  *
    158  */
    159 static size_t
    160 copy_cred(cred_t *src, dl_cred_t *dst)
    161 {
    162 	int n;
    163 	const gid_t *sgrp = crgetgroups(src);
    164 
    165 	n = MIN(NGROUPS_MAX_DEFAULT, crgetngroups(src));
    166 
    167 	/* copy the fixed fields */
    168 	dst->cr_uid = crgetuid(src);
    169 	dst->cr_ruid = crgetruid(src);
    170 	dst->cr_suid = crgetsuid(src);
    171 	dst->cr_gid = crgetgid(src);
    172 	dst->cr_rgid = crgetrgid(src);
    173 	dst->cr_sgid = crgetsgid(src);
    174 	dst->cr_groups[0] = sgrp[0];
    175 
    176 	dst->cr_ngroups = n;
    177 	bcopy(sgrp, (void *)(dst + 1), (n - 1) * sizeof (gid_t));
    178 	return (sizeof (dl_cred_t) + (n - 1) * sizeof (gid_t));
    179 }
    180 
    181 /*
    182  * Sets up for writing to the log files.
    183  */
    184 int
    185 cachefs_dlog_setup(fscache_t *fscp, int createfile)
    186 {
    187 	struct vattr vattr;
    188 	int error = 0;
    189 	int createdone = 0;
    190 	int lookupdone = 0;
    191 	int version = CFS_DLOG_VERSION;
    192 	off_t offset;
    193 	struct cfs_dlog_trailer trailer;
    194 
    195 	mutex_enter(&fscp->fs_dlock);
    196 
    197 	/* all done if the log files already exist */
    198 	if (fscp->fs_dlogfile) {
    199 		ASSERT(fscp->fs_dmapfile);
    200 		goto out;
    201 	}
    202 
    203 	/* see if the log file exists */
    204 	error = VOP_LOOKUP(fscp->fs_fscdirvp, CACHEFS_DLOG_FILE,
    205 	    &fscp->fs_dlogfile, NULL, 0, NULL, kcred, NULL, NULL, NULL);
    206 	if (error && (createfile == 0))
    207 		goto out;
    208 
    209 	/* if the lookup failed then create file log files */
    210 	if (error) {
    211 		createdone++;
    212 
    213 		vattr.va_mode = S_IFREG | 0666;
    214 		vattr.va_uid = 0;
    215 		vattr.va_gid = 0;
    216 		vattr.va_type = VREG;
    217 		vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
    218 		error = VOP_CREATE(fscp->fs_fscdirvp, CACHEFS_DLOG_FILE,
    219 		    &vattr, 0, 0666, &fscp->fs_dlogfile, kcred, 0, NULL, NULL);
    220 		if (error) {
    221 #ifdef CFSDEBUG
    222 			CFS_DEBUG(CFSDEBUG_DLOG)
    223 				printf("cachefs: log file create fail %d\n",
    224 				    error);
    225 #endif
    226 			goto out;
    227 		}
    228 
    229 		/* write the version number into the log file */
    230 		error = vn_rdwr(UIO_WRITE, fscp->fs_dlogfile, (caddr_t)&version,
    231 		    sizeof (version), (offset_t)0, UIO_SYSSPACE, FSYNC,
    232 		    RLIM_INFINITY, kcred, NULL);
    233 		if (error) {
    234 #ifdef CFSDEBUG
    235 			CFS_DEBUG(CFSDEBUG_DLOG)
    236 				printf("cachefs: log file init fail %d\n",
    237 				    error);
    238 #endif
    239 			goto out;
    240 		}
    241 
    242 		vattr.va_mode = S_IFREG | 0666;
    243 		vattr.va_uid = 0;
    244 		vattr.va_gid = 0;
    245 		vattr.va_type = VREG;
    246 		vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
    247 		error = VOP_CREATE(fscp->fs_fscdirvp, CACHEFS_DMAP_FILE,
    248 		    &vattr, 0, 0666, &fscp->fs_dmapfile, kcred, 0, NULL, NULL);
    249 		if (error) {
    250 #ifdef CFSDEBUG
    251 			CFS_DEBUG(CFSDEBUG_DLOG)
    252 				printf("cachefs: map file create fail %d\n",
    253 				    error);
    254 #endif
    255 			goto out;
    256 		}
    257 
    258 		fscp->fs_dlogoff = sizeof (version);
    259 		fscp->fs_dlogseq = 0;
    260 		fscp->fs_dmapoff = 0;
    261 		fscp->fs_dmapsize = 0;
    262 	}
    263 
    264 	/*
    265 	 * Else the lookup succeeded.
    266 	 * Before mounting, fsck should have fixed any problems
    267 	 * in the log file.
    268 	 */
    269 	else {
    270 		lookupdone++;
    271 
    272 		/* find the end of the log file */
    273 		vattr.va_mask = AT_ALL;
    274 		error = VOP_GETATTR(fscp->fs_dlogfile, &vattr, 0, kcred, NULL);
    275 		if (error) {
    276 #ifdef CFSDEBUG
    277 			CFS_DEBUG(CFSDEBUG_DLOG)
    278 				printf("cachefs: log file getattr fail %d\n",
    279 				    error);
    280 #endif
    281 			goto out;
    282 		}
    283 		/*LINTED alignment okay*/
    284 		ASSERT(vattr.va_size <= MAXOFF_T);
    285 		fscp->fs_dlogoff = (off_t)vattr.va_size;
    286 
    287 		offset = vattr.va_size - sizeof (struct cfs_dlog_trailer);
    288 		/*
    289 		 * The last record in the dlog file is a trailer record
    290 		 * that contains the last sequence number used. This is
    291 		 * used to reset the sequence number when a logfile already
    292 		 * exists.
    293 		 */
    294 		error = vn_rdwr(UIO_READ, fscp->fs_dlogfile, (caddr_t)&trailer,
    295 		    sizeof (struct cfs_dlog_trailer), (offset_t)offset,
    296 		    UIO_SYSSPACE, FSYNC, RLIM_INFINITY, kcred, NULL);
    297 		if (error == 0) {
    298 			if (trailer.dl_op == CFS_DLOG_TRAILER) {
    299 				fscp->fs_dlogseq = trailer.dl_seq;
    300 				/*
    301 				 * Set the offset of the next record to be
    302 				 * written, to over write the current
    303 				 * trailer.
    304 				 */
    305 				fscp->fs_dlogoff = offset;
    306 			} else {
    307 #ifdef CFSDEBUG
    308 				CFS_DEBUG(CFSDEBUG_DLOG) {
    309 					cmn_err(CE_WARN,
    310 					    "cachefs: can't find dlog trailer");
    311 					cmn_err(CE_WARN,
    312 					    "cachefs: fsck required");
    313 				}
    314 #endif /* CFSDEBUG */
    315 				/*LINTED alignment okay*/
    316 				fscp->fs_dlogseq = (uint_t)vattr.va_size;
    317 			}
    318 		} else {
    319 #ifdef CFSDEBUG
    320 			CFS_DEBUG(CFSDEBUG_DLOG)
    321 				cmn_err(CE_WARN,
    322 				    "cachefs: error reading dlog trailer");
    323 #endif /* CFSDEBUG */
    324 			/*LINTED alignment okay*/
    325 			fscp->fs_dlogseq = (uint_t)vattr.va_size;
    326 		}
    327 
    328 
    329 		error = VOP_LOOKUP(fscp->fs_fscdirvp, CACHEFS_DMAP_FILE,
    330 		    &fscp->fs_dmapfile, NULL, 0, NULL, kcred, NULL, NULL, NULL);
    331 		if (error) {
    332 #ifdef CFSDEBUG
    333 			CFS_DEBUG(CFSDEBUG_DLOG)
    334 				printf("cachefs: map file lookup fail %d\n",
    335 				    error);
    336 #endif
    337 			goto out;
    338 		}
    339 
    340 		vattr.va_mask = AT_ALL;
    341 		error = VOP_GETATTR(fscp->fs_dmapfile, &vattr, 0, kcred, NULL);
    342 		if (error) {
    343 #ifdef CFSDEBUG
    344 			CFS_DEBUG(CFSDEBUG_DLOG)
    345 				printf("cachefs: map file getattr fail %d\n",
    346 				    error);
    347 #endif
    348 			goto out;
    349 		}
    350 		fscp->fs_dmapoff = (off_t)vattr.va_size;
    351 		fscp->fs_dmapsize = (off_t)vattr.va_size;
    352 	}
    353 
    354 out:
    355 	if (error) {
    356 		if (createdone) {
    357 			if (fscp->fs_dlogfile) {
    358 				VN_RELE(fscp->fs_dlogfile);
    359 				fscp->fs_dlogfile = NULL;
    360 				(void) VOP_REMOVE(fscp->fs_fscdirvp,
    361 				    CACHEFS_DLOG_FILE, kcred, NULL, 0);
    362 			}
    363 			if (fscp->fs_dmapfile) {
    364 				VN_RELE(fscp->fs_dmapfile);
    365 				fscp->fs_dmapfile = NULL;
    366 				(void) VOP_REMOVE(fscp->fs_fscdirvp,
    367 				    CACHEFS_DMAP_FILE, kcred, NULL, 0);
    368 			}
    369 		}
    370 		if (lookupdone) {
    371 			if (fscp->fs_dlogfile) {
    372 				VN_RELE(fscp->fs_dlogfile);
    373 				fscp->fs_dlogfile = NULL;
    374 			}
    375 			if (fscp->fs_dmapfile) {
    376 				VN_RELE(fscp->fs_dmapfile);
    377 				fscp->fs_dmapfile = NULL;
    378 			}
    379 		}
    380 	}
    381 
    382 	mutex_exit(&fscp->fs_dlock);
    383 	return (error);
    384 }
    385 
    386 /*
    387  * Drops reference to the log file.
    388  */
    389 void
    390 cachefs_dlog_teardown(fscache_t *fscp)
    391 {
    392 	vattr_t va;
    393 	/*LINTED: set but not used */
    394 	int error;
    395 
    396 	mutex_enter(&fscp->fs_dlock);
    397 
    398 	/* clean up the log file */
    399 	if (fscp->fs_dlogfile) {
    400 		VN_RELE(fscp->fs_dlogfile);
    401 		fscp->fs_dlogfile = NULL;
    402 	}
    403 
    404 	/* clean up the map file */
    405 	if (fscp->fs_dmapfile) {
    406 		/* set the map file to the actual size needed */
    407 		va.va_mask = AT_SIZE;
    408 		va.va_size = fscp->fs_dmapoff;
    409 		error = VOP_SETATTR(fscp->fs_dmapfile, &va, 0, kcred, NULL);
    410 #ifdef CFSDEBUG
    411 		if (error) {
    412 			cmn_err(CE_WARN, "cachefs: map setattr failed %d",
    413 			    error);
    414 		}
    415 #endif
    416 		VN_RELE(fscp->fs_dmapfile);
    417 		fscp->fs_dmapfile = NULL;
    418 	}
    419 	mutex_exit(&fscp->fs_dlock);
    420 }
    421 
    422 /*
    423  * Outputs a dlog message to the log file.
    424  */
    425 static off_t
    426 cachefs_dlog_output(fscache_t *fscp, cfs_dlog_entry_t *entp, uint_t *seqp)
    427 {
    428 	int error;
    429 	off_t offset;
    430 	int xx;
    431 	uint_t seq;
    432 	int len;
    433 	struct cfs_dlog_trailer *trail;
    434 
    435 	ASSERT(entp->dl_len <= CFS_DLOG_ENTRY_MAXSIZE);
    436 
    437 	if (fscp->fs_dlogfile == NULL) {
    438 		error = cachefs_dlog_setup(fscp, 1);
    439 		if (error) {
    440 			offset = 0;
    441 			goto out;
    442 		}
    443 	}
    444 
    445 	/* round up length to a 4 byte boundary */
    446 	len = entp->dl_len;
    447 	xx = len & 0x03;
    448 	if (xx) {
    449 		xx = 4 - xx;
    450 		bzero((void *)((uintptr_t)entp + len), (size_t)xx);
    451 		len += xx;
    452 		entp->dl_len = len;
    453 	}
    454 
    455 	/* XXX turn this on/off in sync with code in cachefs_dlog_setsecattr */
    456 #if 0
    457 	/* XXX debugging hack, round up to 16 byte boundary */
    458 	len = entp->dl_len;
    459 	xx = 16 - (len & 0x0f);
    460 	bcopy("UUUUUUUUUUUUUUUU", (void *)((uintptr_t)entp + len), (size_t)xx);
    461 	len += xx;
    462 	entp->dl_len = len;
    463 #endif
    464 
    465 	/*
    466 	 * All functions which allocate a dlog entry buffer must be sure
    467 	 * to allocate space for the trailer record. The trailer record,
    468 	 * is always located at the end of the log file. It contains the
    469 	 * highest sequence number used. This allows cachefs_dlog_setup()
    470 	 * to reset the sequence numbers properly when the log file
    471 	 * already exists.
    472 	 */
    473 	trail = (struct cfs_dlog_trailer *)((uintptr_t)entp + entp->dl_len);
    474 	trail->dl_len = sizeof (struct cfs_dlog_trailer);
    475 	trail->dl_op = CFS_DLOG_TRAILER;
    476 	trail->dl_valid = CFS_DLOG_VAL_COMMITTED;
    477 	mutex_enter(&fscp->fs_dlock);
    478 	ASSERT(fscp->fs_dlogfile);
    479 
    480 	/* get a sequence number for this log entry */
    481 	seq = fscp->fs_dlogseq + 1;
    482 	if (seq == 0) {
    483 		mutex_exit(&fscp->fs_dlock);
    484 		offset = 0;
    485 #ifdef CFSDEBUG
    486 		cmn_err(CE_WARN, "cachefs: logging failed, seq overflow");
    487 #endif
    488 		goto out;
    489 	}
    490 	fscp->fs_dlogseq++;
    491 	trail->dl_seq = fscp->fs_dlogseq;
    492 
    493 	/* add the sequence number to the record */
    494 	entp->dl_seq = seq;
    495 
    496 	/* get offset into file to write record */
    497 	offset = fscp->fs_dlogoff;
    498 
    499 	/* try to write the record to the log file */
    500 	/*
    501 	 * NOTE This write will over write the previous trailer record and
    502 	 * will add a new trailer record. This is done with a single
    503 	 * write for performance reasons.
    504 	 */
    505 	error = vn_rdwr(UIO_WRITE, fscp->fs_dlogfile, (caddr_t)entp,
    506 	    entp->dl_len+trail->dl_len, (offset_t)offset, UIO_SYSSPACE, FSYNC,
    507 	    RLIM_INFINITY, kcred, NULL);
    508 
    509 	if (error) {
    510 		offset = 0;
    511 		cmn_err(CE_WARN, "cachefs: logging failed (%d)", error);
    512 	} else {
    513 		fscp->fs_dlogoff += entp->dl_len;
    514 
    515 		/* get offset of valid field */
    516 		offset += offsetof(struct cfs_dlog_entry, dl_valid);
    517 	}
    518 
    519 	mutex_exit(&fscp->fs_dlock);
    520 
    521 	/* return sequence number used if requested */
    522 	if (seqp)
    523 		*seqp = seq;
    524 
    525 out:
    526 	return (offset);
    527 }
    528 
    529 /*
    530  * Commits a previously written dlog message.
    531  */
    532 int
    533 cachefs_dlog_commit(fscache_t *fscp, off_t offset, int error)
    534 {
    535 	cfs_dlog_val_t valid;
    536 
    537 	if (error)
    538 		valid = CFS_DLOG_VAL_ERROR;
    539 	else
    540 		valid = CFS_DLOG_VAL_COMMITTED;
    541 
    542 	error = vn_rdwr(UIO_WRITE, fscp->fs_dlogfile,
    543 	    (caddr_t)&valid, sizeof (valid), (offset_t)offset,
    544 	    UIO_SYSSPACE, FSYNC, RLIM_INFINITY, kcred, NULL);
    545 
    546 	if (error)
    547 		cmn_err(CE_WARN, "cachefs: logging commit failed (%d)", error);
    548 	return (error);
    549 }
    550 
    551 /*
    552  * Reserves space in the map file.
    553  */
    554 static int
    555 cachefs_dlog_mapreserve(fscache_t *fscp, int size)
    556 {
    557 	int error = 0;
    558 	int len;
    559 	char *bufp;
    560 
    561 	if (fscp->fs_dmapfile == NULL) {
    562 		error = cachefs_dlog_setup(fscp, 1);
    563 		if (error) {
    564 			return (error);
    565 		}
    566 	}
    567 
    568 	mutex_enter(&fscp->fs_dlock);
    569 	ASSERT(fscp->fs_dmapoff <= fscp->fs_dmapsize);
    570 	ASSERT(fscp->fs_dmapfile);
    571 
    572 	if ((fscp->fs_dmapoff + size) > fscp->fs_dmapsize) {
    573 		/* reserve 20% for optimal hashing */
    574 		size += MAXBSIZE / 5;
    575 
    576 		/* grow file by a MAXBSIZE chunk */
    577 		len = MAXBSIZE;
    578 		ASSERT((fscp->fs_dmapoff + size) < (fscp->fs_dmapsize + len));
    579 
    580 		bufp = cachefs_kmem_zalloc(len, KM_SLEEP);
    581 		error = vn_rdwr(UIO_WRITE, fscp->fs_dmapfile, (caddr_t)bufp,
    582 			len, (offset_t)fscp->fs_dmapsize, UIO_SYSSPACE, FSYNC,
    583 			RLIM_INFINITY, kcred, NULL);
    584 		if (error == 0) {
    585 			fscp->fs_dmapoff += size;
    586 			fscp->fs_dmapsize += len;
    587 		} else {
    588 			cmn_err(CE_WARN, "cachefs: logging secondary "
    589 			    "failed (%d)", error);
    590 		}
    591 		cachefs_kmem_free(bufp, len);
    592 	} else {
    593 		fscp->fs_dmapoff += size;
    594 	}
    595 	mutex_exit(&fscp->fs_dlock);
    596 	return (error);
    597 }
    598 
    599 /*
    600  * Reserves space for one cid mapping in the mapping file.
    601  */
    602 int
    603 cachefs_dlog_cidmap(fscache_t *fscp)
    604 {
    605 	int error;
    606 	error = cachefs_dlog_mapreserve(fscp,
    607 	    sizeof (struct cfs_dlog_mapping_space));
    608 	return (error);
    609 }
    610 
    611 off_t
    612 cachefs_dlog_setattr(fscache_t *fscp, struct vattr *vap, int flags,
    613     cnode_t *cp, cred_t *cr)
    614 {
    615 	struct cfs_dlog_entry *entp;
    616 	struct cfs_dlog_setattr *up;
    617 	size_t	len;
    618 	off_t offset;
    619 
    620 	ASSERT(MUTEX_HELD(&cp->c_statelock));
    621 
    622 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
    623 
    624 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    625 	entp->dl_op = CFS_DLOG_SETATTR;
    626 	up = &entp->dl_u.dl_setattr;
    627 	CACHEFS_DLOG_VATTR_COPY(vap, &up->dl_attrs,
    628 		"cachefs_dlog_setattr: dl_attr");
    629 	up->dl_flags = flags;
    630 	up->dl_cid = cp->c_id;
    631 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
    632 		&up->dl_times.tm_mtime, "cachefs_dlog_setattr: ", "mtime");
    633 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
    634 		&up->dl_times.tm_ctime, "cachefs_dlog_setattr: ", "ctime");
    635 
    636 	/* store the cred info */
    637 	len = copy_cred(cr, &up->dl_cred);
    638 
    639 	/* Calculate the length of this record */
    640 	entp->dl_len = (int)(((uintptr_t)&up->dl_cred + len) - (uintptr_t)entp);
    641 
    642 	/* write the record in the log */
    643 	offset = cachefs_dlog_output(fscp, entp, NULL);
    644 
    645 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
    646 	return (offset);
    647 }
    648 
    649 off_t
    650 /*ARGSUSED*/
    651 cachefs_dlog_setsecattr(fscache_t *fscp, vsecattr_t *vsec, int flags,
    652     cnode_t *cp, cred_t *cr)
    653 {
    654 	struct cfs_dlog_entry *entp;
    655 	struct cfs_dlog_setsecattr *up;
    656 	size_t alen, clen, len;
    657 	off_t offset = 0;
    658 	aclent_t *aclp;
    659 
    660 	ASSERT(MUTEX_HELD(&cp->c_statelock));
    661 
    662 	/* paranoia */
    663 	ASSERT((vsec->vsa_mask & VSA_ACL) || (vsec->vsa_aclcnt == 0));
    664 	ASSERT((vsec->vsa_mask & VSA_DFACL) || (vsec->vsa_dfaclcnt == 0));
    665 	if ((vsec->vsa_mask & VSA_ACL) == 0)
    666 		vsec->vsa_aclcnt = 0;
    667 	if ((vsec->vsa_mask & VSA_DFACL) == 0)
    668 		vsec->vsa_dfaclcnt = 0;
    669 
    670 	/* calculate length of ACL and cred data */
    671 	alen = sizeof (aclent_t) * (vsec->vsa_aclcnt + vsec->vsa_dfaclcnt);
    672 	clen = sizeof (dl_cred_t) + (((long)crgetngroups(cr)) * sizeof (gid_t));
    673 
    674 	/*
    675 	 * allocate entry.  ACLs may be up to 24k currently, but they
    676 	 * usually won't, so we don't want to make cfs_dlog_entry_t
    677 	 * too big.  so, we must compute the length here.
    678 	 */
    679 
    680 	len = sizeof (cfs_dlog_entry_t) - sizeof (up->dl_buffer) -
    681 		sizeof (up->dl_cred) + alen + clen;
    682 
    683 
    684 #if 0
    685 	/* make up for weird behavior in cachefs_dlog_output */
    686 	/* XXX turn this on/off in sync with code in cachefs_dlog_output */
    687 	entp = cachefs_kmem_alloc(len + 32 + sizeof (struct cfs_dlog_trailer),
    688 	    KM_SLEEP);
    689 #else
    690 	entp = cachefs_kmem_alloc(len, KM_SLEEP);
    691 #endif
    692 
    693 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    694 	entp->dl_op = CFS_DLOG_SETSECATTR;
    695 
    696 	up = &entp->dl_u.dl_setsecattr;
    697 	up->dl_cid = cp->c_id;
    698 
    699 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
    700 		&up->dl_times.tm_mtime, "cachefs_dlog_setsecattr: ", "mtime");
    701 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
    702 		&up->dl_times.tm_ctime, "cachefs_dlog_setsecattr: ", "ctime");
    703 
    704 	/* get the creds */
    705 	(void) copy_cred(cr, &up->dl_cred);
    706 
    707 	/* mask and counts */
    708 	up->dl_mask = vsec->vsa_mask;
    709 	up->dl_aclcnt = vsec->vsa_aclcnt;
    710 	up->dl_dfaclcnt = vsec->vsa_dfaclcnt;
    711 
    712 	/* get the acls themselves */
    713 	aclp = (aclent_t *)((uintptr_t)(&up->dl_cred) + clen);
    714 	if (vsec->vsa_aclcnt > 0) {
    715 		bcopy(vsec->vsa_aclentp, aclp,
    716 		    vsec->vsa_aclcnt * sizeof (aclent_t));
    717 		aclp += vsec->vsa_aclcnt;
    718 	}
    719 	if (vsec->vsa_dfaclcnt > 0) {
    720 		bcopy(vsec->vsa_dfaclentp, aclp,
    721 		    vsec->vsa_dfaclcnt * sizeof (aclent_t));
    722 	}
    723 
    724 	entp->dl_len = (int)len;
    725 
    726 	offset = cachefs_dlog_output(fscp, entp, NULL);
    727 
    728 #if 0
    729 	/* XXX turn on/off in sync with code in cachefs_dlog_output */
    730 	cachefs_kmem_free(entp, len + 32 + sizeof (struct cfs_dlog_trailer));
    731 #else
    732 	cachefs_kmem_free(entp, len);
    733 #endif
    734 
    735 	return (offset);
    736 }
    737 
    738 off_t
    739 cachefs_dlog_create(fscache_t *fscp, cnode_t *pcp, char *nm,
    740     vattr_t *vap, int excl, int mode, cnode_t *cp, int exists, cred_t *cr)
    741 {
    742 	struct cfs_dlog_entry *entp;
    743 	struct cfs_dlog_create *up;
    744 	size_t len;
    745 	caddr_t curp;
    746 	off_t offset;
    747 
    748 	ASSERT(MUTEX_HELD(&cp->c_statelock));
    749 
    750 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
    751 
    752 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    753 	entp->dl_op = CFS_DLOG_CREATE;
    754 	up = &entp->dl_u.dl_create;
    755 	up->dl_parent_cid = pcp->c_id;
    756 	up->dl_new_cid = cp->c_id;
    757 	CACHEFS_DLOG_VATTR_COPY(vap, &up->dl_attrs,
    758 		"cachefs_dlog_create: dl_attr");
    759 	up->dl_excl = excl;
    760 	up->dl_mode = mode;
    761 	up->dl_exists = exists;
    762 	bzero(&up->dl_fid, sizeof (up->dl_fid));
    763 	if (exists) {
    764 		CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
    765 			&up->dl_times.tm_mtime,
    766 			"cachefs_dlog_create: ", "mtime");
    767 		CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
    768 			&up->dl_times.tm_ctime,
    769 			"cachefs_dlog_create: ", "ctime");
    770 	} else {
    771 		up->dl_times.tm_ctime.tv_sec = 0;
    772 		up->dl_times.tm_ctime.tv_nsec = 0;
    773 		up->dl_times.tm_mtime.tv_sec = 0;
    774 		up->dl_times.tm_mtime.tv_nsec = 0;
    775 	}
    776 
    777 	/* store the cred info */
    778 	len = copy_cred(cr, &up->dl_cred);
    779 
    780 	/* find the address in buffer past where the creds are stored */
    781 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
    782 
    783 	/* store the created name */
    784 	len = strlen(nm) + 1;
    785 	bcopy(nm, curp, len);
    786 
    787 	/* calculate the length of this record */
    788 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
    789 
    790 	/* write the record in the log */
    791 	offset = cachefs_dlog_output(fscp, entp, NULL);
    792 
    793 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
    794 	return (offset);
    795 }
    796 
    797 off_t
    798 cachefs_dlog_remove(fscache_t *fscp, cnode_t *pcp, char *nm, cnode_t *cp,
    799     cred_t *cr)
    800 {
    801 	struct cfs_dlog_entry *entp;
    802 	struct cfs_dlog_remove *up;
    803 	size_t len;
    804 	caddr_t curp;
    805 	off_t offset;
    806 
    807 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
    808 
    809 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    810 	entp->dl_op = CFS_DLOG_REMOVE;
    811 	up = &entp->dl_u.dl_remove;
    812 	up->dl_parent_cid = pcp->c_id;
    813 	up->dl_child_cid = cp->c_id;
    814 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
    815 		&up->dl_times.tm_mtime, "cachefs_dlog_remove: ", "mtime");
    816 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
    817 		&up->dl_times.tm_ctime, "cachefs_dlog_remove: ", "ctime");
    818 	/* store the cred info */
    819 	len = copy_cred(cr, &up->dl_cred);
    820 
    821 	/* find the address in buffer past where the creds are stored */
    822 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
    823 
    824 	/* store the removed name */
    825 	len = strlen(nm) + 1;
    826 	bcopy(nm, curp, len);
    827 
    828 	/* calculate the length of this record */
    829 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
    830 
    831 	/* write the record in the log */
    832 	offset = cachefs_dlog_output(fscp, entp, NULL);
    833 
    834 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
    835 	return (offset);
    836 }
    837 
    838 off_t
    839 cachefs_dlog_link(fscache_t *fscp, cnode_t *pcp, char *nm, cnode_t *cp,
    840     cred_t *cr)
    841 {
    842 	struct cfs_dlog_entry *entp;
    843 	struct cfs_dlog_link *up;
    844 	size_t len;
    845 	caddr_t curp;
    846 	off_t offset;
    847 
    848 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
    849 
    850 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    851 	entp->dl_op = CFS_DLOG_LINK;
    852 	up = &entp->dl_u.dl_link;
    853 	up->dl_parent_cid = pcp->c_id;
    854 	up->dl_child_cid = cp->c_id;
    855 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
    856 		&up->dl_times.tm_mtime, "cachefs_dlog_link: ", "mtime");
    857 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
    858 		&up->dl_times.tm_ctime, "cachefs_dlog_link: ", "ctime");
    859 
    860 	/* store the cred info */
    861 	len = copy_cred(cr, &up->dl_cred);
    862 
    863 	/* find the address in buffer past where the creds are stored */
    864 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
    865 
    866 	/* store the link name */
    867 	len = strlen(nm) + 1;
    868 	bcopy(nm, curp, len);
    869 
    870 	/* calculate the length of this record */
    871 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
    872 
    873 	/* write the record in the log */
    874 	offset = cachefs_dlog_output(fscp, entp, NULL);
    875 
    876 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
    877 	return (offset);
    878 }
    879 
    880 off_t
    881 cachefs_dlog_rename(fscache_t *fscp, cnode_t *odcp, char *onm, cnode_t *ndcp,
    882     char *nnm, cred_t *cr, cnode_t *cp, cnode_t *delcp)
    883 {
    884 	struct cfs_dlog_entry *entp;
    885 	struct cfs_dlog_rename *up;
    886 	size_t len;
    887 	caddr_t curp;
    888 	off_t offset;
    889 
    890 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
    891 
    892 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    893 	entp->dl_op = CFS_DLOG_RENAME;
    894 	up = &entp->dl_u.dl_rename;
    895 	up->dl_oparent_cid = odcp->c_id;
    896 	up->dl_nparent_cid = ndcp->c_id;
    897 	up->dl_child_cid = cp->c_id;
    898 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
    899 		&up->dl_times.tm_mtime, "cachefs_dlog_rename: ", "mtime");
    900 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
    901 		&up->dl_times.tm_ctime, "cachefs_dlog_rename: ", "ctime");
    902 	if (delcp) {
    903 		up->dl_del_cid = delcp->c_id;
    904 		CACHEFS_DLOG_TS_COPY(&delcp->c_metadata.md_vattr.va_mtime,
    905 			&up->dl_del_times.tm_mtime,
    906 			"cachefs_dlog_rename: ", "del mtime");
    907 		CACHEFS_DLOG_TS_COPY(&delcp->c_metadata.md_vattr.va_ctime,
    908 			&up->dl_del_times.tm_ctime,
    909 			"cachefs_dlog_rename: ", "del ctime");
    910 	} else {
    911 		up->dl_del_cid.cid_fileno = 0;
    912 		up->dl_del_cid.cid_flags = 0;
    913 		up->dl_del_times.tm_mtime.tv_sec = 0;
    914 		up->dl_del_times.tm_mtime.tv_nsec = 0;
    915 		up->dl_del_times.tm_ctime.tv_sec = 0;
    916 		up->dl_del_times.tm_ctime.tv_nsec = 0;
    917 	}
    918 
    919 	/* store the cred info */
    920 	len = copy_cred(cr, &up->dl_cred);
    921 
    922 	/* find the address in buffer past where the creds are stored */
    923 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
    924 
    925 	/* store the old name */
    926 	len = strlen(onm) + 1;
    927 	bcopy(onm, curp, len);
    928 
    929 	/* store the new name */
    930 	curp += len;
    931 	len = strlen(nnm) + 1;
    932 	bcopy(nnm, curp, len);
    933 
    934 	/* calculate the length of this record */
    935 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
    936 
    937 	/* write the record in the log */
    938 	offset = cachefs_dlog_output(fscp, entp, NULL);
    939 
    940 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
    941 	return (offset);
    942 }
    943 
    944 off_t
    945 cachefs_dlog_mkdir(fscache_t *fscp, cnode_t *pcp, cnode_t *cp, char *nm,
    946     vattr_t *vap, cred_t *cr)
    947 {
    948 	struct cfs_dlog_entry *entp;
    949 	struct cfs_dlog_mkdir *up;
    950 	size_t len;
    951 	caddr_t curp;
    952 	off_t offset;
    953 
    954 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
    955 
    956 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
    957 	entp->dl_op = CFS_DLOG_MKDIR;
    958 	up = &entp->dl_u.dl_mkdir;
    959 	up->dl_parent_cid = pcp->c_id;
    960 	up->dl_child_cid = cp->c_id;
    961 	CACHEFS_DLOG_VATTR_COPY(vap, &up->dl_attrs,
    962 		"cachefs_dlog_mkdir: dl_attr");
    963 	bzero(&up->dl_fid, sizeof (up->dl_fid));
    964 
    965 	/* store the cred info */
    966 	len = copy_cred(cr, &up->dl_cred);
    967 
    968 	/* find the address in buffer past where the creds are stored */
    969 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
    970 
    971 	/* store the new directory name */
    972 	len = strlen(nm) + 1;
    973 	bcopy(nm, curp, len);
    974 
    975 	/* calculate the length of this record */
    976 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
    977 
    978 	/* write the record in the dlog */
    979 	offset = cachefs_dlog_output(fscp, entp, NULL);
    980 
    981 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
    982 	return (offset);
    983 }
    984 
    985 off_t
    986 cachefs_dlog_rmdir(fscache_t *fscp, cnode_t *pcp, char *nm, cnode_t *cp,
    987     cred_t *cr)
    988 {
    989 	struct cfs_dlog_entry *entp;
    990 	struct cfs_dlog_rmdir *up;
    991 	size_t len;
    992 	caddr_t curp;
    993 	off_t offset;
    994 
    995 	/* if not a local dir, log the cid to fid mapping */
    996 	if ((cp->c_id.cid_flags & CFS_CID_LOCAL) == 0) {
    997 		if (cachefs_dlog_mapfid(fscp, cp))
    998 			return (0);
    999 		if (cachefs_dlog_cidmap(fscp))
   1000 			return (0);
   1001 	}
   1002 
   1003 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
   1004 
   1005 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
   1006 	entp->dl_op = CFS_DLOG_RMDIR;
   1007 	up = &entp->dl_u.dl_rmdir;
   1008 	up->dl_parent_cid = pcp->c_id;
   1009 
   1010 	/* store the cred info */
   1011 	len = copy_cred(cr, &up->dl_cred);
   1012 
   1013 	/* find the address in buffer past where the creds are stored */
   1014 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
   1015 
   1016 	/* store the created name */
   1017 	len = strlen(nm) + 1;
   1018 	bcopy(nm, curp, len);
   1019 
   1020 	/* calculate the length of this record */
   1021 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
   1022 
   1023 	/* write the record in the log */
   1024 	offset = cachefs_dlog_output(fscp, entp, NULL);
   1025 
   1026 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
   1027 	return (offset);
   1028 }
   1029 
   1030 off_t
   1031 cachefs_dlog_symlink(fscache_t *fscp, cnode_t *pcp, cnode_t *cp, char *lnm,
   1032     vattr_t *vap, char *tnm, cred_t *cr)
   1033 {
   1034 	struct cfs_dlog_entry *entp;
   1035 	struct cfs_dlog_symlink *up;
   1036 	size_t len;
   1037 	caddr_t curp;
   1038 	off_t offset;
   1039 
   1040 	ASSERT(MUTEX_HELD(&cp->c_statelock));
   1041 
   1042 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
   1043 
   1044 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
   1045 	entp->dl_op = CFS_DLOG_SYMLINK;
   1046 	up = &entp->dl_u.dl_symlink;
   1047 	up->dl_parent_cid = pcp->c_id;
   1048 	up->dl_child_cid = cp->c_id;
   1049 	CACHEFS_DLOG_VATTR_COPY(vap, &up->dl_attrs,
   1050 		"cachefs_dlog_symlink: dl_attr");
   1051 	up->dl_times.tm_ctime.tv_sec = 0;
   1052 	up->dl_times.tm_ctime.tv_nsec = 0;
   1053 	up->dl_times.tm_mtime.tv_sec = 0;
   1054 	up->dl_times.tm_mtime.tv_nsec = 0;
   1055 	bzero(&up->dl_fid, sizeof (up->dl_fid));
   1056 
   1057 	/* store the cred info */
   1058 	len = copy_cred(cr, &up->dl_cred);
   1059 
   1060 	/* find the address in buffer past where the creds are stored */
   1061 	curp = (caddr_t)(((uintptr_t)&up->dl_cred) + len);
   1062 
   1063 	/* store the link name */
   1064 	len = strlen(lnm) + 1;
   1065 	bcopy(lnm, curp, len);
   1066 
   1067 	/* store new name */
   1068 	curp += len;
   1069 	len = strlen(tnm) + 1;
   1070 	bcopy(tnm, curp, len);
   1071 
   1072 	/* calculate the length of this record */
   1073 	entp->dl_len = (int)(((uintptr_t)curp + len) - (uintptr_t)entp);
   1074 
   1075 	/* write the record in the log */
   1076 	offset = cachefs_dlog_output(fscp, entp, NULL);
   1077 
   1078 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
   1079 	return (offset);
   1080 }
   1081 
   1082 off_t
   1083 cachefs_dlog_modify(fscache_t *fscp, cnode_t *cp, cred_t *cr, uint_t *seqp)
   1084 {
   1085 	struct cfs_dlog_entry *entp;
   1086 	struct cfs_dlog_modify *up;
   1087 	off_t offset;
   1088 	uint_t seq;
   1089 	size_t len;
   1090 
   1091 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
   1092 
   1093 	entp->dl_valid = CFS_DLOG_VAL_CRASH;
   1094 	entp->dl_op = CFS_DLOG_MODIFIED;
   1095 	up = &entp->dl_u.dl_modify;
   1096 	up->dl_cid = cp->c_id;
   1097 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_mtime,
   1098 		&up->dl_times.tm_mtime,
   1099 		"cachefs_dlog_modify: ", "mtime");
   1100 	CACHEFS_DLOG_TS_COPY(&cp->c_metadata.md_vattr.va_ctime,
   1101 		&up->dl_times.tm_ctime,
   1102 		"cachefs_dlog_modify: ", "ctime");
   1103 
   1104 	up->dl_next = 0;
   1105 
   1106 	/* store the cred info */
   1107 	len = copy_cred(cr, &up->dl_cred);
   1108 
   1109 	/* calculate the length of this record */
   1110 	entp->dl_len = (int)(((uintptr_t)&up->dl_cred + len) - (uintptr_t)entp);
   1111 
   1112 	/* write the record in the log */
   1113 	offset = cachefs_dlog_output(fscp, entp, &seq);
   1114 
   1115 	/* return sequence number */
   1116 	*seqp = seq;
   1117 
   1118 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
   1119 	return (offset);
   1120 }
   1121 
   1122 int
   1123 cachefs_dlog_mapfid(fscache_t *fscp, cnode_t *cp)
   1124 {
   1125 	struct cfs_dlog_entry *entp;
   1126 	struct cfs_dlog_mapfid *up;
   1127 	off_t offset;
   1128 
   1129 	entp = cachefs_kmem_alloc(sizeof (cfs_dlog_entry_t), KM_SLEEP);
   1130 
   1131 	entp->dl_valid = CFS_DLOG_VAL_COMMITTED;
   1132 	entp->dl_op = CFS_DLOG_MAPFID;
   1133 	up = &entp->dl_u.dl_mapfid;
   1134 	up->dl_cid = cp->c_id;
   1135 	CACHEFS_FID_COPY(&cp->c_cookie, &up->dl_fid);
   1136 
   1137 	/* calculate the length of this record */
   1138 	/* entp->dl_len = ((caddr_t)up - (caddr_t)entp + sizeof (*up)); */
   1139 	entp->dl_len = (int)(offsetof(struct cfs_dlog_entry, dl_u.dl_mapfid) +
   1140 				sizeof (struct cfs_dlog_mapfid));
   1141 
   1142 	/* write the record in the log */
   1143 	offset = cachefs_dlog_output(fscp, entp, NULL);
   1144 
   1145 	cachefs_kmem_free(entp, sizeof (cfs_dlog_entry_t));
   1146 	return (offset == 0);
   1147 }
   1148 
   1149 /* Returns the next sequence number, 0 if an error */
   1150 uint_t
   1151 cachefs_dlog_seqnext(fscache_t *fscp)
   1152 {
   1153 	int error;
   1154 	uint_t seq;
   1155 
   1156 	if (fscp->fs_dlogfile == NULL) {
   1157 		error = cachefs_dlog_setup(fscp, 1);
   1158 		if (error)
   1159 			return (0);
   1160 	}
   1161 
   1162 	mutex_enter(&fscp->fs_dlock);
   1163 	ASSERT(fscp->fs_dlogfile);
   1164 
   1165 	/* get a sequence number for this log entry */
   1166 	seq = fscp->fs_dlogseq + 1;
   1167 	if (seq != 0) {
   1168 		fscp->fs_dlogseq++;
   1169 	}
   1170 #ifdef CFSDEBUG
   1171 	else {
   1172 		cmn_err(CE_WARN, "cachefs: logging failed, seq overflow 2.");
   1173 	}
   1174 #endif
   1175 	mutex_exit(&fscp->fs_dlock);
   1176 	return (seq);
   1177 }
   1178