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