xref: /titanic_44/usr/src/uts/common/fs/cachefs/cachefs_log.c (revision ea8dc4b6d2251b437950c0056bc626b311c73c27)
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 2005 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/errno.h>
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/user.h>
34 #include <sys/stat.h>
35 #include <sys/kstat.h>
36 #include <sys/time.h>
37 #include <sys/vfs.h>
38 #include <sys/vnode.h>
39 #include <sys/file.h>
40 #include <rpc/types.h>
41 #include <rpc/xdr.h>
42 #include <sys/mode.h>
43 #include <sys/pathname.h>
44 #include <sys/cmn_err.h>
45 #include <sys/debug.h>
46 #include <sys/fs/cachefs_fs.h>
47 #include <sys/fs/cachefs_log.h>
48 #include <vm/seg.h>
49 #include <vm/seg_map.h>
50 #include <sys/sysmacros.h>
51 
52 /*
53  * ino64_t is a unsigned long on LP64 and unsigned long long on ILP32,
54  * the compiler emits many warnings when calling xdr_u_longlong_t with an
55  * unsigned long pointer on LP64 even though it's safe.
56  */
57 #define	xdr_ino64(xdrs, p)	xdr_u_longlong_t((xdrs), (u_longlong_t *)(p))
58 
59 /*
60  * cfs_time_t is an int in both LP64 and ILP32. To avoid compiler warnings
61  * define its xdr here explicitely
62  */
63 #define	xdr_cfs_time_t(xdrs, p)	xdr_int((xdrs), (int *)(p))
64 
65 #define	CACHEFS_LOG_MAX_BUFFERED	65536
66 #define	CACHEFS_LOG_LOWATER		 8192
67 #define	CACHEFS_LOG_ENCODE_SIZE		 4096
68 
69 #if (defined(_SYSCALL32_IMPL) || defined(_LP64))
70 
71 #define	OUT_IF_TIME_OVERFLOW(cachep, time)				\
72 	if (TIME_OVERFLOW(time)) {					\
73 		cachefs_log_error(cachep, EOVERFLOW, 1);		\
74 		goto out;						\
75 	}
76 
77 #define	RET_IF_TIME_OVERFLOW(cachep, time)				\
78 	if (TIME_OVERFLOW(time)) {					\
79 		cachefs_log_error(cachep, EOVERFLOW, 1);		\
80 		return;							\
81 	}
82 
83 #else /* not (_SYSCALL32_IMPL || _LP64) */
84 
85 #define	OUT_IF_TIME_OVERFLOW(cachep, time)
86 
87 #define	RET_IF_TIME_OVERFLOW(cachep, time)
88 
89 #endif /* (_SYSCALL32_IMPL || _LP64) */
90 
91 typedef struct cachefs_log_work_list {
92 	void *data;
93 	size_t size;
94 	xdrproc_t translate;
95 	struct cachefs_log_work_list *next;
96 } *cachefs_log_work_list_t;
97 
98 /* forward declarations of static functions */
99 static void cachefs_log_enqueue(cachefscache_t *, void *, int, xdrproc_t);
100 static int cachefs_log_save_lc(cachefscache_t *);
101 static int cachefs_log_write_header(struct vnode *, cachefscache_t *, int);
102 
103 static bool_t cachefs_xdr_logfile_header(XDR *,
104     struct cachefs_log_logfile_header *);
105 static bool_t cachefs_xdr_mount(XDR *, struct cachefs_log_mount_record *);
106 static bool_t cachefs_xdr_umount(XDR *, struct cachefs_log_umount_record *);
107 static bool_t cachefs_xdr_getpage(XDR *, struct cachefs_log_getpage_record *);
108 static bool_t cachefs_xdr_readdir(XDR *, struct cachefs_log_readdir_record *);
109 static bool_t cachefs_xdr_readlink(XDR *,
110     struct cachefs_log_readlink_record *);
111 static bool_t cachefs_xdr_remove(XDR *, struct cachefs_log_remove_record *);
112 static bool_t cachefs_xdr_rmdir(XDR *, struct cachefs_log_rmdir_record *);
113 static bool_t cachefs_xdr_truncate(XDR *,
114     struct cachefs_log_truncate_record *);
115 static bool_t cachefs_xdr_putpage(XDR *, struct cachefs_log_putpage_record *);
116 static bool_t cachefs_xdr_create(XDR *, struct cachefs_log_create_record *);
117 static bool_t cachefs_xdr_mkdir(XDR *, struct cachefs_log_mkdir_record *);
118 static bool_t cachefs_xdr_rename(XDR *, struct cachefs_log_rename_record *);
119 static bool_t cachefs_xdr_symlink(XDR *, struct cachefs_log_symlink_record *);
120 static bool_t cachefs_xdr_populate(XDR *,
121     struct cachefs_log_populate_record *);
122 static bool_t cachefs_xdr_csymlink(XDR *,
123     struct cachefs_log_csymlink_record *);
124 static bool_t cachefs_xdr_filldir(XDR *,
125     struct cachefs_log_filldir_record *);
126 static bool_t cachefs_xdr_mdcreate(XDR *,
127     struct cachefs_log_mdcreate_record *);
128 static bool_t cachefs_xdr_gpfront(XDR *,
129     struct cachefs_log_gpfront_record *);
130 static bool_t cachefs_xdr_rfdir(XDR *,
131     struct cachefs_log_rfdir_record *);
132 static bool_t cachefs_xdr_ualloc(XDR *,
133     struct cachefs_log_ualloc_record *);
134 static bool_t cachefs_xdr_calloc(XDR *,
135     struct cachefs_log_calloc_record *);
136 static bool_t cachefs_xdr_nocache(XDR *,
137     struct cachefs_log_nocache_record *);
138 
139 
140 extern time_t time;
141 
142 /*
143  * cachefs_log_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
144  *
145  * called from /dev/kstat or somesuch.
146  *
147  */
148 
149 int
150 cachefs_log_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
151 {
152 	cachefs_log_control_t *lc = (cachefs_log_control_t *)ksp->ks_data;
153 	cachefs_log_control_t *buflc = (cachefs_log_control_t *)buf;
154 	cachefscache_t *cachep = (cachefscache_t *)(uintptr_t)lc->lc_cachep;
155 	cachefs_log_cookie_t *cl = cachep->c_log;
156 	int error = 0;
157 
158 	ASSERT(MUTEX_HELD(&cachep->c_log_mutex));
159 
160 	/* if they just want to read the kstat, get that out of the way. */
161 	if (rw != KSTAT_WRITE) {
162 		bcopy(lc, buflc, sizeof (*lc));
163 		return (0);
164 	}
165 
166 	/* make sure they're passing us a valid control cookie */
167 	if ((buflc->lc_cachep != lc->lc_cachep) ||
168 	    (buflc->lc_magic != CACHEFS_LOG_MAGIC))
169 		return (EIO);
170 
171 	/*
172 	 * if logging is currently off
173 	 *   o insist that we're being handed a logfile path
174 	 *   o set cl, and give our cachep its value
175 	 *
176 	 * after that, if something goes wrong, we must call
177 	 * cachefs_log_error to clear cachep->c_log.
178 	 */
179 	if (cl == NULL) {
180 		if (buflc->lc_path[0] == '\0')
181 			return (EIO);
182 		cl = cachep->c_log = cachefs_log_create_cookie(lc);
183 		if (cl == NULL) {
184 			cachefs_log_error(cachep, ENOMEM, 0);
185 			return (EIO);
186 		}
187 	}
188 
189 	/*
190 	 * if we're being handed an empty logpath, then they must be
191 	 * turning off logging; also, logging must have been turned on
192 	 * before, or else the previous paragraph would have caught
193 	 * it.
194 	 */
195 	if (buflc->lc_path[0] == '\0') {
196 		cachefs_log_process_queue(cachep, 0);
197 		cachep->c_log = NULL;
198 		cachefs_log_destroy_cookie(cl);
199 		bzero(lc, sizeof (*lc));
200 		lc->lc_magic = CACHEFS_LOG_MAGIC;
201 		lc->lc_cachep = (uint64_t)(uintptr_t)cachep;
202 		(void) VOP_REMOVE(cachep->c_dirvp, LOG_STATUS_NAME, kcred);
203 		return (0);
204 	}
205 
206 	/*
207 	 * if we get here, we know that we're being handed a valid log
208 	 * control cookie, and that a path is set.  try to open the
209 	 * log file, even if it's the same path, because they might
210 	 * have removed the old log file out from under us.  if it
211 	 * really is the same file, no harm done.
212 	 */
213 	if ((error = cachefs_log_logfile_open(cachep, buflc->lc_path)) != 0) {
214 		cachefs_log_error(cachep, error, 0);
215 		return (EIO);
216 	}
217 
218 	/*
219 	 * if we get here, we have a valid logfile open.  we don't do
220 	 * anything here with the bitmap of what's being logged, other
221 	 * than copy it.  we're home free!
222 	 */
223 	bcopy(buflc, lc, sizeof (*lc));
224 	if ((error = cachefs_log_save_lc(cachep)) != 0) {
225 		cachefs_log_error(cachep, error, 0);
226 		return (EIO);
227 	}
228 
229 	return (0);
230 }
231 
232 static int
233 cachefs_log_save_lc(cachefscache_t *cachep)
234 {
235 	cachefs_log_control_t *lc = (cachefs_log_control_t *)cachep->c_log_ctl;
236 	struct vnode *savevp;
237 	struct vattr attr;
238 	int error = 0;
239 
240 	if (lc == NULL)
241 		return (EINVAL);
242 
243 	attr.va_mode = S_IFREG | 0666;
244 	attr.va_uid = 0;
245 	attr.va_gid = 0;
246 	attr.va_type = VREG;
247 	attr.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
248 
249 	if (((error = VOP_LOOKUP(cachep->c_dirvp, LOG_STATUS_NAME, &savevp,
250 	    NULL, 0, NULL, kcred)) != 0) &&
251 	    ((error = VOP_CREATE(cachep->c_dirvp, LOG_STATUS_NAME, &attr, EXCL,
252 	    0600, &savevp, kcred, 0)) != 0))
253 		return (error);
254 	ASSERT(savevp != NULL);
255 	if (savevp == NULL)
256 		return (ENOENT);
257 
258 	error = vn_rdwr(UIO_WRITE, savevp,
259 	    (caddr_t)lc, sizeof (*lc),
260 	    0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL);
261 
262 	VN_RELE(savevp);
263 
264 	return (error);
265 }
266 
267 /*
268  * cachefs_log_cookie_t *cachefs_log_create_cookie(void *)
269  *
270  * creates and initializes the cookie, which lives in cachep.  called
271  * from either a kstat write which turns on logging, or from
272  * initializing cachep when a log-info-file exists.
273  */
274 
275 cachefs_log_cookie_t *
276 cachefs_log_create_cookie(cachefs_log_control_t *lc)
277 {
278 	cachefs_log_cookie_t *rc;
279 
280 	rc = cachefs_kmem_zalloc(sizeof (*rc), KM_NOSLEEP);
281 	if (rc == NULL)
282 		return (NULL);
283 
284 	rc->cl_magic = CACHEFS_LOG_MAGIC;
285 	rc->cl_logctl = lc;
286 
287 	return (rc);
288 }
289 
290 /*
291  * void cachefs_log_destroy_cookie(cachefs_log_cookie_t *)
292  *
293  * destroys the log cookie.  called from cachefs_log_error, or from
294  * destroying the cachep.
295  *
296  */
297 
298 void
299 cachefs_log_destroy_cookie(cachefs_log_cookie_t *cl)
300 {
301 	cachefs_log_work_list_t node, oldnode;
302 
303 	if (cl == NULL)
304 		return;
305 
306 	ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
307 
308 	cl->cl_magic++;
309 	node = cl->cl_head;
310 	while (node != NULL) {
311 		cachefs_kmem_free(node->data, node->size);
312 		oldnode = node;
313 		node = node->next;
314 		cachefs_kmem_free(oldnode, sizeof (*oldnode));
315 	}
316 	if (cl->cl_logvp != NULL)
317 		VN_RELE(cl->cl_logvp);
318 	cachefs_kmem_free(cl, sizeof (*cl));
319 }
320 
321 /*
322  * int cachefs_log_logfile_open(cachefscache_t *, char *)
323  *
324  * opens the logfile, and stores the path string if its successful.
325  *
326  * returns an errno if one occured.
327  *
328  */
329 
330 int
331 cachefs_log_logfile_open(cachefscache_t *cachep, char *path)
332 {
333 	cachefs_log_cookie_t *cl = cachep->c_log;
334 	struct vnode *newvp = NULL;
335 	int error = 0;
336 	int i;
337 
338 	ASSERT(MUTEX_HELD(&cachep->c_log_mutex));
339 	ASSERT(cl != NULL);
340 	ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
341 
342 	/* lookup the pathname -- it must already exist! */
343 	error = lookupname(path, UIO_SYSSPACE, FOLLOW, NULL, &newvp);
344 	if (error)
345 		goto out;
346 	ASSERT(newvp != NULL);
347 	if (newvp == NULL) {
348 		error = ENOENT; /* XXX this shouldn't happen (yeah right) */
349 		goto out;
350 	}
351 
352 	/* easy out if we just re-opened the same logfile */
353 	if (cl->cl_logvp == newvp) {
354 		VN_RELE(newvp);
355 		goto out;
356 	}
357 
358 	/* XXX we may change this to allow named pipes */
359 	if (newvp->v_type != VREG) {
360 		error = EINVAL;
361 		goto out;
362 	}
363 	if (vn_matchops(newvp, cachefs_getvnodeops())) {
364 		error = EINVAL;
365 		goto out;
366 	}
367 
368 	/* write out the header */
369 	error = cachefs_log_write_header(newvp, cachep, 0);
370 	if (error)
371 		goto out;
372 
373 	/* if we get here, we successfully opened the log. */
374 	if (cl->cl_logvp != NULL)
375 		VN_RELE(cl->cl_logvp);
376 	cl->cl_logvp = newvp;
377 
378 	/*
379 	 * `fake' a mount entry for each mounted cachefs filesystem.
380 	 * this is overkill, but it's easiest and most foolproof way
381 	 * to do things here.  the user-level consumers of the logfile
382 	 * have to expect extraneous mount entries and deal with it
383 	 * correctly.
384 	 */
385 	mutex_exit(&cachep->c_log_mutex);
386 	for (i = 0; i < cachefs_kstat_key_n; i++) {
387 		cachefs_kstat_key_t *k;
388 		struct vfs *vfsp;
389 		struct fscache *fscp;
390 
391 		k = cachefs_kstat_key + i;
392 		if (! k->ks_mounted)
393 			continue;
394 
395 		vfsp = (struct vfs *)(uintptr_t)k->ks_vfsp;
396 		fscp = VFS_TO_FSCACHE(vfsp);
397 		cachefs_log_mount(cachep, 0, vfsp, fscp,
398 		    (char *)(uintptr_t)k->ks_mountpoint, UIO_SYSSPACE,
399 		    (char *)(uintptr_t)k->ks_cacheid);
400 	}
401 	mutex_enter(&cachep->c_log_mutex);
402 
403 out:
404 	if ((error != 0) && (newvp != NULL))
405 		VN_RELE(newvp);
406 	return (error);
407 }
408 
409 /*
410  * called when an error occured during logging.  send the error to
411  * syslog, invalidate the logfile, and stop logging.
412  */
413 
414 void
415 cachefs_log_error(cachefscache_t *cachep, int error, int getlock)
416 {
417 	cachefs_log_cookie_t *cl = cachep->c_log;
418 	cachefs_log_control_t *lc = cachep->c_log_ctl;
419 	int writable = 0;
420 
421 	ASSERT((getlock) || (MUTEX_HELD(&cachep->c_log_mutex)));
422 
423 	if (getlock)
424 		mutex_enter(&cachep->c_log_mutex);
425 
426 	if ((cachep->c_flags & (CACHE_NOCACHE | CACHE_NOFILL)) == 0)
427 		writable = 1;
428 
429 	cmn_err(CE_WARN, "cachefs logging: error %d\n", error);
430 
431 	if ((writable) && (cl != NULL) && (cl->cl_logvp != NULL))
432 		(void) cachefs_log_write_header(cl->cl_logvp, cachep, error);
433 
434 	cachep->c_log = NULL;
435 	if (cl != NULL)
436 		cachefs_log_destroy_cookie(cl);
437 	bzero(lc, sizeof (cachefs_log_control_t));
438 	lc->lc_magic = CACHEFS_LOG_MAGIC;
439 	lc->lc_cachep = (uint64_t)(uintptr_t)cachep;
440 	if (writable)
441 		(void) VOP_REMOVE(cachep->c_dirvp, LOG_STATUS_NAME, kcred);
442 
443 	if (getlock)
444 		mutex_exit(&cachep->c_log_mutex);
445 }
446 
447 static int
448 cachefs_log_write_header(struct vnode *vp, cachefscache_t *cachep, int error)
449 {
450 	struct cachefs_log_logfile_header header, oheader;
451 	char buffy[2 * sizeof (header)];
452 	int Errno = 0;
453 	struct vattr attr;
454 	int gotold = 0;
455 	XDR xdrm;
456 
457 	attr.va_mask = AT_SIZE;
458 	if ((error = VOP_GETATTR(vp, &attr, 0, kcred)) != 0)
459 		goto out;
460 	if (attr.va_size != 0) {
461 		error = vn_rdwr(UIO_READ, vp, buffy,
462 		    MIN(sizeof (buffy), attr.va_size),
463 		    0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
464 		if (error != 0)
465 			goto out;
466 
467 		xdrm.x_ops = NULL;
468 		xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_DECODE);
469 		if ((xdrm.x_ops == NULL) ||
470 		    (! cachefs_xdr_logfile_header(&xdrm, &oheader))) {
471 			if (xdrm.x_ops != NULL)
472 				xdr_destroy(&xdrm);
473 			error = EINVAL;
474 			goto out;
475 		}
476 		xdr_destroy(&xdrm);
477 		gotold = 1;
478 
479 		if (oheader.lh_magic != CACHEFS_LOG_MAGIC) {
480 			error = EINVAL;
481 			goto out;
482 		}
483 	}
484 
485 	xdrm.x_ops = NULL;
486 
487 	xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_ENCODE);
488 
489 	if (gotold) {
490 		header = oheader;
491 	} else {
492 		header.lh_magic = CACHEFS_LOG_MAGIC;
493 		header.lh_revision = CACHEFS_LOG_FILE_REV;
494 		header.lh_blocks = cachep->c_usage.cu_blksused;
495 		header.lh_files = cachep->c_usage.cu_filesused;
496 		header.lh_maxbsize = MAXBSIZE;
497 		header.lh_pagesize = PAGESIZE;
498 	}
499 
500 	/* these are things that we stomp over for every header write */
501 	header.lh_errno = Errno;
502 
503 	if (! cachefs_xdr_logfile_header(&xdrm, &header)) {
504 		error = ENOMEM;
505 		goto out;
506 	}
507 
508 	error = vn_rdwr(UIO_WRITE, vp,
509 	    (caddr_t)buffy, xdr_getpos(&xdrm),
510 	    0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL);
511 	if (error)
512 		goto out;
513 
514 out:
515 	if (xdrm.x_ops != NULL)
516 		xdr_destroy(&xdrm);
517 	return (error);
518 }
519 
520 /*
521  * enqueues a record to be written to the logfile.
522  */
523 
524 static void
525 cachefs_log_enqueue(cachefscache_t *cachep, void *record, int size,
526     xdrproc_t translate)
527 {
528 	cachefs_log_cookie_t *cl;
529 	cachefs_log_work_list_t newnode, oldnode;
530 
531 	mutex_enter(&cachep->c_log_mutex);
532 	cl = cachep->c_log;
533 
534 	if (cl == NULL) { /* someone turned off logging out from under us */
535 		mutex_exit(&cachep->c_log_mutex);
536 		cachefs_kmem_free(record, size);
537 		return;
538 	}
539 	ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
540 
541 	cl->cl_size += size;
542 	newnode = cachefs_kmem_zalloc(sizeof (*newnode), KM_NOSLEEP);
543 	if ((cl->cl_size > CACHEFS_LOG_MAX_BUFFERED) || (newnode == NULL)) {
544 		cachefs_log_error(cachep, ENOMEM, 0);
545 		if (newnode != NULL)
546 			cachefs_kmem_free(newnode, sizeof (*newnode));
547 		cachefs_kmem_free(record, size);
548 		mutex_exit(&cachep->c_log_mutex);
549 		return;
550 	}
551 
552 	newnode->data = record;
553 	newnode->size = size;
554 	newnode->translate = translate;
555 	newnode->next = NULL;
556 
557 	oldnode = (cachefs_log_work_list_t)cl->cl_tail;
558 	if (oldnode != NULL)
559 		oldnode->next = newnode;
560 	cl->cl_tail = newnode;
561 	if (cl->cl_head == NULL)
562 		cl->cl_head = newnode;
563 	mutex_exit(&cachep->c_log_mutex);
564 
565 	if (cl->cl_size >= CACHEFS_LOG_LOWATER) {
566 		mutex_enter(&cachep->c_workq.wq_queue_lock);
567 		cachep->c_workq.wq_logwork = 1;
568 		cv_signal(&cachep->c_workq.wq_req_cv);
569 		mutex_exit(&cachep->c_workq.wq_queue_lock);
570 	}
571 }
572 
573 /*
574  * processes the log queue.  run by an async worker thread, or via
575  * cachefs_cache_sync().
576  */
577 
578 void
579 cachefs_log_process_queue(cachefscache_t *cachep, int getlock)
580 {
581 	cachefs_log_cookie_t *cl;
582 	cachefs_log_work_list_t work, workhead, oldwork;
583 	struct vnode *logvp = NULL;
584 	struct uio uio;
585 	struct iovec iov;
586 	int error = 0;
587 	XDR xdrm;
588 	char *buffy = NULL;
589 
590 	/*
591 	 * NULL out the x_ops field of XDR.  this way, if x_ops !=
592 	 * NULL, we know that we did the xdr*_create() successfully.
593 	 * this is documented in the xdr_create man page.
594 	 */
595 
596 	xdrm.x_ops = NULL;
597 
598 	/* see if we're still logging */
599 	if (getlock)
600 		mutex_enter(&cachep->c_log_mutex);
601 	cl = cachep->c_log;
602 	if ((cl == NULL) || (cl->cl_magic != CACHEFS_LOG_MAGIC)) {
603 		if (getlock)
604 			mutex_exit(&cachep->c_log_mutex);
605 		return;
606 	}
607 
608 	/* get the work, and let go of the mutex asap. */
609 	workhead = cl->cl_head;
610 	cl->cl_head = cl->cl_tail = NULL;
611 	cl->cl_size = 0;
612 	logvp = cl->cl_logvp;
613 	ASSERT(logvp != NULL);
614 	if (logvp == NULL) {
615 		if (getlock)
616 			mutex_exit(&cachep->c_log_mutex);
617 		return;
618 	}
619 	VN_HOLD(logvp);
620 	if (getlock)
621 		mutex_exit(&cachep->c_log_mutex);
622 
623 	/* we don't use vn_rdwr() because there's no way to set FNONBLOCK */
624 
625 	uio.uio_iov = &iov;
626 	uio.uio_iovcnt = 1;
627 	uio.uio_loffset = 0; /* fake -- we do FAPPEND */
628 	uio.uio_segflg = (short)UIO_SYSSPACE;
629 	uio.uio_llimit = MAXOFFSET_T;
630 	uio.uio_fmode = FWRITE | FNONBLOCK;
631 	uio.uio_extflg = UIO_COPY_CACHED;
632 
633 	buffy = cachefs_kmem_alloc(CACHEFS_LOG_ENCODE_SIZE, KM_SLEEP);
634 	xdrmem_create(&xdrm, buffy, CACHEFS_LOG_ENCODE_SIZE, XDR_ENCODE);
635 
636 	(void) VOP_RWLOCK(logvp, V_WRITELOCK_TRUE, NULL);
637 	for (work = workhead; work != NULL; work = work->next) {
638 		if (! (work->translate)(&xdrm, work->data)) {
639 			VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
640 			error = ENOMEM;
641 			goto out;
642 		}
643 
644 		iov.iov_base = buffy;
645 		iov.iov_len = uio.uio_resid = xdr_getpos(&xdrm);
646 		(void) xdr_setpos(&xdrm, 0);
647 
648 		error = VOP_WRITE(logvp, &uio, FAPPEND, kcred, NULL);
649 
650 		/* XXX future -- check for EAGAIN */
651 
652 		if ((error) || (uio.uio_resid)) {
653 			if (uio.uio_resid != 0)
654 				error = EIO;
655 			VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
656 			goto out;
657 		}
658 	}
659 	VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
660 
661 out:
662 	if (xdrm.x_ops != NULL)
663 		xdr_destroy(&xdrm);
664 	if (buffy != NULL)
665 		cachefs_kmem_free(buffy, CACHEFS_LOG_ENCODE_SIZE);
666 
667 	/*
668 	 * if an error occured, we need to free the buffers ourselves.
669 	 * cachefs_destory_cookie() can't do it.
670 	 */
671 
672 	work = workhead;
673 	while (work != NULL) {
674 		cachefs_kmem_free(work->data, work->size);
675 		oldwork = work;
676 		work = work->next;
677 		cachefs_kmem_free(oldwork, sizeof (*oldwork));
678 	}
679 	if (logvp != NULL)
680 		VN_RELE(logvp);
681 	if (error) {
682 		cachefs_log_error(cachep, error, 1);
683 		return;
684 	}
685 }
686 
687 static bool_t
688 cachefs_xdr_logfile_header(XDR *xdrs, struct cachefs_log_logfile_header *h)
689 {
690 	if ((! xdr_u_int(xdrs, &h->lh_magic)) ||
691 	    (! xdr_u_int(xdrs, &h->lh_revision)) ||
692 	    (! xdr_int(xdrs, &h->lh_errno)) ||
693 	    (! xdr_u_int(xdrs, &h->lh_blocks)) ||
694 	    (! xdr_u_int(xdrs, &h->lh_files)) ||
695 	    (! xdr_u_int(xdrs, &h->lh_maxbsize)) ||
696 	    (! xdr_u_int(xdrs, &h->lh_pagesize)))
697 		return (FALSE);
698 
699 	return (TRUE);
700 }
701 
702 /*
703  * the routines for logging each transaction follow...
704  */
705 
706 void
707 cachefs_log_mount(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
708     fscache_t *fscp, char *upath, enum uio_seg seg, char *cacheid)
709 {
710 	struct cachefs_log_mount_record *record;
711 	char *cacheidt;
712 	char *path = NULL;
713 	size_t len;
714 	int len1, len2;
715 	int size, error;
716 
717 	/* In Solaris 64 - if can't represent time don't bother */
718 	OUT_IF_TIME_OVERFLOW(cachep, time)
719 	if (seg == UIO_USERSPACE) {
720 		path = cachefs_kmem_alloc(MAXPATHLEN, KM_NOSLEEP);
721 		if (path == NULL) {
722 			cachefs_log_error(cachep, ENOMEM, 1);
723 			goto out;
724 		}
725 		if ((error = copyinstr(upath, path, MAXPATHLEN, &len)) != 0) {
726 			cachefs_log_error(cachep, error, 1);
727 			goto out;
728 		}
729 	} else {
730 		path = upath;
731 	}
732 
733 	len1 = (path != NULL) ? strlen(path) : 0;
734 	len2 = (cacheid != NULL) ? strlen(cacheid) : 0;
735 	size = (int)sizeof (*record) + len1 + len2 -
736 	    (int)CLPAD(cachefs_log_mount_record, path);
737 	record = cachefs_kmem_zalloc(size, KM_NOSLEEP);
738 	if (record == NULL) {
739 		cachefs_log_error(cachep, ENOMEM, 1);
740 		goto out;
741 	}
742 
743 	record->type = CACHEFS_LOG_MOUNT;
744 	record->time = time;
745 
746 	record->error = Errno;
747 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
748 
749 	if (fscp) {
750 		record->flags = fscp->fs_info.fi_mntflags;
751 		record->popsize = fscp->fs_info.fi_popsize;
752 		record->fgsize = fscp->fs_info.fi_fgsize;
753 	}
754 
755 	record->pathlen = (ushort_t)len1;
756 	record->cacheidlen = (ushort_t)len2;
757 	if (path != NULL)
758 		(void) strcpy(record->path, path);
759 	cacheidt = record->path + len1 + 1;
760 	if (cacheid != NULL)
761 		(void) strcpy(cacheidt, cacheid);
762 
763 	cachefs_log_enqueue(cachep, record, size, cachefs_xdr_mount);
764 
765 out:
766 	if ((seg == UIO_USERSPACE) && (path != NULL))
767 		cachefs_kmem_free(path, MAXPATHLEN);
768 }
769 
770 static bool_t
771 cachefs_xdr_mount(XDR *xdrs, struct cachefs_log_mount_record *rec)
772 {
773 	char *path = rec->path;
774 	char *cacheid;
775 
776 	cacheid = path + strlen(path) + 1;
777 
778 	if ((! xdr_int(xdrs, &rec->type)) ||
779 	    (! xdr_int(xdrs, &rec->error)) ||
780 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
781 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
782 	    (! xdr_u_int(xdrs, &rec->flags)) ||
783 	    (! xdr_u_int(xdrs, &rec->popsize)) ||
784 	    (! xdr_u_int(xdrs, &rec->fgsize)) ||
785 	    (! xdr_u_short(xdrs, &rec->pathlen)) ||
786 	    (! xdr_u_short(xdrs, &rec->cacheidlen)) ||
787 	    (! xdr_wrapstring(xdrs, &path)) ||
788 	    (! xdr_wrapstring(xdrs, &cacheid)))
789 		return (FALSE);
790 
791 	return (TRUE);
792 }
793 
794 void
795 cachefs_log_umount(cachefscache_t *cachep, int Errno, struct vfs *vfsp)
796 {
797 	struct cachefs_log_umount_record *record;
798 
799 	/* In Solaris 64 - if can't represent time don't bother */
800 	RET_IF_TIME_OVERFLOW(cachep, time)
801 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
802 	if (record == NULL) {
803 		cachefs_log_error(cachep, ENOMEM, 1);
804 		return;
805 	}
806 
807 	record->type = CACHEFS_LOG_UMOUNT;
808 	record->time = time;
809 
810 	record->error = Errno;
811 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
812 
813 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
814 	    cachefs_xdr_umount);
815 }
816 
817 static bool_t
818 cachefs_xdr_umount(XDR *xdrs, struct cachefs_log_umount_record *rec)
819 {
820 	if ((! xdr_int(xdrs, &rec->type)) ||
821 	    (! xdr_int(xdrs, &rec->error)) ||
822 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
823 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))))
824 		return (FALSE);
825 
826 	return (TRUE);
827 }
828 
829 void
830 cachefs_log_getpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
831     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len)
832 {
833 	struct cachefs_log_getpage_record *record;
834 
835 	/* In Solaris 64 - if can't represent time don't bother */
836 	RET_IF_TIME_OVERFLOW(cachep, time)
837 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
838 	if (record == NULL) {
839 		cachefs_log_error(cachep, ENOMEM, 1);
840 		return;
841 	}
842 
843 	record->type = CACHEFS_LOG_GETPAGE;
844 	record->time = time;
845 
846 	record->error = Errno;
847 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
848 	if (fidp != NULL) {
849 		CACHEFS_FID_COPY(fidp, &record->fid);
850 	}
851 	record->fileno = fileno;
852 	record->uid = uid;
853 	record->offset = offset;
854 	record->len = (uint_t)len;
855 
856 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
857 	    cachefs_xdr_getpage);
858 }
859 
860 static bool_t
861 cachefs_xdr_getpage(XDR *xdrs, struct cachefs_log_getpage_record *rec)
862 {
863 	if ((! xdr_int(xdrs, &rec->type)) ||
864 	    (! xdr_int(xdrs, &rec->error)) ||
865 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
866 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
867 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
868 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
869 	    (! xdr_int(xdrs, &rec->uid)) ||
870 	    (! xdr_u_longlong_t(xdrs, &rec->offset)) ||
871 	    (! xdr_u_int(xdrs, &rec->len)))
872 		return (FALSE);
873 
874 	return (TRUE);
875 }
876 
877 void
878 cachefs_log_readdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
879     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, int eof)
880 {
881 	struct cachefs_log_readdir_record *record;
882 
883 	/* In Solaris 64 - if can't represent time don't bother */
884 	RET_IF_TIME_OVERFLOW(cachep, time)
885 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
886 	if (record == NULL) {
887 		cachefs_log_error(cachep, ENOMEM, 1);
888 		return;
889 	}
890 
891 	record->type = CACHEFS_LOG_READDIR;
892 	record->time = time;
893 
894 	record->error = Errno;
895 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
896 	if (fidp != NULL) {
897 		CACHEFS_FID_COPY(fidp, &record->fid);
898 	}
899 	record->fileno = fileno;
900 	record->uid = uid;
901 	record->offset = offset;
902 	record->eof = eof;
903 
904 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
905 	    cachefs_xdr_readdir);
906 }
907 
908 static bool_t
909 cachefs_xdr_readdir(XDR *xdrs, struct cachefs_log_readdir_record *rec)
910 {
911 	if ((! xdr_int(xdrs, &rec->type)) ||
912 	    (! xdr_int(xdrs, &rec->error)) ||
913 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
914 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
915 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
916 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
917 	    (! xdr_int(xdrs, &rec->uid)) ||
918 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) ||
919 	    (! xdr_int(xdrs, &rec->eof)))
920 		return (FALSE);
921 
922 	return (TRUE);
923 }
924 
925 void
926 cachefs_log_readlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
927     fid_t *fidp, ino64_t fileno, uid_t uid, size_t length)
928 {
929 	struct cachefs_log_readlink_record *record;
930 
931 	/* In Solaris 64 - if can't represent time don't bother */
932 	RET_IF_TIME_OVERFLOW(cachep, time)
933 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
934 	if (record == NULL) {
935 		cachefs_log_error(cachep, ENOMEM, 1);
936 		return;
937 	}
938 
939 	record->type = CACHEFS_LOG_READLINK;
940 	record->time = time;
941 
942 	record->error = Errno;
943 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
944 	if (fidp != NULL) {
945 		CACHEFS_FID_COPY(fidp, &record->fid);
946 	}
947 	record->fileno = fileno;
948 	record->uid = uid;
949 	record->length = (uint_t)length;
950 
951 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
952 	    cachefs_xdr_readlink);
953 }
954 
955 static bool_t
956 cachefs_xdr_readlink(XDR *xdrs, struct cachefs_log_readlink_record *rec)
957 {
958 	if ((! xdr_int(xdrs, &rec->type)) ||
959 	    (! xdr_int(xdrs, &rec->error)) ||
960 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
961 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
962 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
963 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
964 	    (! xdr_int(xdrs, &rec->uid)) ||
965 	    (! xdr_u_int(xdrs, &rec->length)))
966 		return (FALSE);
967 
968 	return (TRUE);
969 }
970 
971 void
972 cachefs_log_remove(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
973     fid_t *fidp, ino64_t fileno, uid_t uid)
974 {
975 	struct cachefs_log_remove_record *record;
976 
977 	/* In Solaris 64 - if can't represent time don't bother */
978 	RET_IF_TIME_OVERFLOW(cachep, time)
979 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
980 	if (record == NULL) {
981 		cachefs_log_error(cachep, ENOMEM, 1);
982 		return;
983 	}
984 
985 	record->type = CACHEFS_LOG_REMOVE;
986 	record->time = time;
987 
988 	record->error = Errno;
989 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
990 	if (fidp != NULL) {
991 		CACHEFS_FID_COPY(fidp, &record->fid);
992 	}
993 	record->fileno = fileno;
994 	record->uid = uid;
995 
996 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
997 	    cachefs_xdr_remove);
998 }
999 
1000 static bool_t
1001 cachefs_xdr_remove(XDR *xdrs, struct cachefs_log_remove_record *rec)
1002 {
1003 	if ((! xdr_int(xdrs, &rec->type)) ||
1004 	    (! xdr_int(xdrs, &rec->error)) ||
1005 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1006 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1007 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1008 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1009 	    (! xdr_int(xdrs, &rec->uid)))
1010 		return (FALSE);
1011 
1012 	return (TRUE);
1013 }
1014 
1015 void
1016 cachefs_log_rmdir(cachefscache_t *cachep, int Errno,
1017     struct vfs *vfsp, fid_t *fidp, ino64_t fileno, uid_t uid)
1018 {
1019 	struct cachefs_log_rmdir_record *record;
1020 
1021 	/* In Solaris 64 - if can't represent time don't bother */
1022 	RET_IF_TIME_OVERFLOW(cachep, time)
1023 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1024 	if (record == NULL) {
1025 		cachefs_log_error(cachep, ENOMEM, 1);
1026 		return;
1027 	}
1028 
1029 	record->type = CACHEFS_LOG_RMDIR;
1030 	record->time = time;
1031 
1032 	record->error = Errno;
1033 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1034 	if (fidp != NULL) {
1035 		CACHEFS_FID_COPY(fidp, &record->fid);
1036 	}
1037 	record->fileno = fileno;
1038 	record->uid = uid;
1039 
1040 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1041 	    cachefs_xdr_rmdir);
1042 }
1043 
1044 static bool_t
1045 cachefs_xdr_rmdir(XDR *xdrs, struct cachefs_log_rmdir_record *rec)
1046 {
1047 	if ((! xdr_int(xdrs, &rec->type)) ||
1048 	    (! xdr_int(xdrs, &rec->error)) ||
1049 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1050 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1051 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1052 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1053 	    (! xdr_int(xdrs, &rec->uid)))
1054 		return (FALSE);
1055 
1056 	return (TRUE);
1057 }
1058 
1059 void
1060 cachefs_log_truncate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1061     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t size)
1062 {
1063 	struct cachefs_log_truncate_record *record;
1064 
1065 	/* In Solaris 64 - if can't represent time don't bother */
1066 	RET_IF_TIME_OVERFLOW(cachep, time)
1067 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1068 	if (record == NULL) {
1069 		cachefs_log_error(cachep, ENOMEM, 1);
1070 		return;
1071 	}
1072 
1073 	record->type = CACHEFS_LOG_TRUNCATE;
1074 	record->time = time;
1075 
1076 	record->error = Errno;
1077 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1078 	if (fidp != NULL) {
1079 		CACHEFS_FID_COPY(fidp, &record->fid);
1080 	}
1081 	record->fileno = fileno;
1082 	record->uid = uid;
1083 	record->size = size;
1084 
1085 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1086 	    cachefs_xdr_truncate);
1087 }
1088 
1089 static bool_t
1090 cachefs_xdr_truncate(XDR *xdrs, struct cachefs_log_truncate_record *rec)
1091 {
1092 	if ((! xdr_int(xdrs, &rec->type)) ||
1093 	    (! xdr_int(xdrs, &rec->error)) ||
1094 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1095 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1096 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1097 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1098 	    (! xdr_int(xdrs, &rec->uid)) ||
1099 	    (! xdr_u_longlong_t(xdrs, &rec->size)))
1100 		return (FALSE);
1101 
1102 	return (TRUE);
1103 }
1104 
1105 void
1106 cachefs_log_putpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1107     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len)
1108 {
1109 	struct cachefs_log_putpage_record *record;
1110 
1111 	/* In Solaris 64 - if can't represent time don't bother */
1112 	RET_IF_TIME_OVERFLOW(cachep, time)
1113 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1114 	if (record == NULL) {
1115 		cachefs_log_error(cachep, ENOMEM, 1);
1116 		return;
1117 	}
1118 
1119 	record->type = CACHEFS_LOG_PUTPAGE;
1120 	record->time = time;
1121 
1122 	record->error = Errno;
1123 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1124 	if (fidp != NULL) {
1125 		CACHEFS_FID_COPY(fidp, &record->fid);
1126 	}
1127 	record->fileno = fileno;
1128 	record->uid = uid;
1129 	record->offset = offset;
1130 	record->len = (uint_t)len;
1131 
1132 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1133 	    cachefs_xdr_putpage);
1134 }
1135 
1136 static bool_t
1137 cachefs_xdr_putpage(XDR *xdrs, struct cachefs_log_putpage_record *rec)
1138 {
1139 	if ((! xdr_int(xdrs, &rec->type)) ||
1140 	    (! xdr_int(xdrs, &rec->error)) ||
1141 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1142 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1143 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1144 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1145 	    (! xdr_int(xdrs, &rec->uid)) ||
1146 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) ||
1147 	    (! xdr_u_int(xdrs, &rec->len)))
1148 		return (FALSE);
1149 
1150 	return (TRUE);
1151 }
1152 
1153 void
1154 cachefs_log_create(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1155     fid_t *filefidp, ino64_t fileno, uid_t uid)
1156 {
1157 	struct cachefs_log_create_record *record;
1158 
1159 	/* In Solaris 64 - if can't represent time don't bother */
1160 	RET_IF_TIME_OVERFLOW(cachep, time)
1161 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1162 	if (record == NULL) {
1163 		cachefs_log_error(cachep, ENOMEM, 1);
1164 		return;
1165 	}
1166 
1167 	record->type = CACHEFS_LOG_CREATE;
1168 	record->time = time;
1169 
1170 	record->error = Errno;
1171 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1172 	if (filefidp != NULL) {
1173 		CACHEFS_FID_COPY(filefidp, &record->fid);
1174 	}
1175 	record->fileno = fileno;
1176 	record->uid = uid;
1177 
1178 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1179 	    cachefs_xdr_create);
1180 }
1181 
1182 static bool_t
1183 cachefs_xdr_create(XDR *xdrs, struct cachefs_log_create_record *rec)
1184 {
1185 	if ((! xdr_int(xdrs, &rec->type)) ||
1186 	    (! xdr_int(xdrs, &rec->error)) ||
1187 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1188 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1189 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1190 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1191 	    (! xdr_int(xdrs, &rec->uid)))
1192 		return (FALSE);
1193 
1194 	return (TRUE);
1195 }
1196 
1197 void
1198 cachefs_log_mkdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1199     fid_t *cfidp, ino64_t fileno, uid_t uid)
1200 {
1201 	struct cachefs_log_mkdir_record *record;
1202 	int size;
1203 
1204 	/* In Solaris 64 - if can't represent time don't bother */
1205 	RET_IF_TIME_OVERFLOW(cachep, time)
1206 	size = (int)sizeof (*record);
1207 	record = cachefs_kmem_zalloc(size, KM_NOSLEEP);
1208 	if (record == NULL) {
1209 		cachefs_log_error(cachep, ENOMEM, 1);
1210 		return;
1211 	}
1212 
1213 	record->type = CACHEFS_LOG_MKDIR;
1214 	record->time = time;
1215 
1216 	record->error = Errno;
1217 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1218 	if (cfidp != NULL) {
1219 		CACHEFS_FID_COPY(cfidp, &record->fid);
1220 	}
1221 	record->fileno = fileno;
1222 	record->uid = uid;
1223 
1224 	cachefs_log_enqueue(cachep, record, size,
1225 	    cachefs_xdr_mkdir);
1226 }
1227 
1228 static bool_t
1229 cachefs_xdr_mkdir(XDR *xdrs, struct cachefs_log_mkdir_record *rec)
1230 {
1231 	if ((! xdr_int(xdrs, &rec->type)) ||
1232 	    (! xdr_int(xdrs, &rec->error)) ||
1233 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1234 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1235 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1236 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1237 	    (! xdr_int(xdrs, &rec->uid)))
1238 		return (FALSE);
1239 
1240 	return (TRUE);
1241 }
1242 
1243 void
1244 cachefs_log_rename(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1245     fid_t *gfp, ino64_t fileno, int removed, uid_t uid)
1246 {
1247 	struct cachefs_log_rename_record *record;
1248 
1249 	/* In Solaris 64 - if can't represent time don't bother */
1250 	RET_IF_TIME_OVERFLOW(cachep, time)
1251 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1252 	if (record == NULL) {
1253 		cachefs_log_error(cachep, ENOMEM, 1);
1254 		return;
1255 	}
1256 
1257 	record->type = CACHEFS_LOG_RENAME;
1258 	record->time = time;
1259 
1260 	record->error = Errno;
1261 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1262 	if (gfp != NULL) {
1263 		CACHEFS_FID_COPY(gfp, &record->gone);
1264 	}
1265 	record->fileno = fileno;
1266 	record->removed = removed;
1267 	record->uid = uid;
1268 
1269 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1270 	    cachefs_xdr_rename);
1271 }
1272 
1273 static bool_t
1274 cachefs_xdr_rename(XDR *xdrs, struct cachefs_log_rename_record *rec)
1275 {
1276 	if ((! xdr_int(xdrs, &rec->type)) ||
1277 	    (! xdr_int(xdrs, &rec->error)) ||
1278 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1279 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1280 	    (! xdr_opaque(xdrs, (caddr_t)&rec->gone, sizeof (rec->gone))) ||
1281 	    (! xdr_int(xdrs, &rec->removed)) ||
1282 	    (! xdr_int(xdrs, &rec->uid)))
1283 		return (FALSE);
1284 
1285 	return (TRUE);
1286 }
1287 
1288 
1289 void
1290 cachefs_log_symlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1291     fid_t *fidp, ino64_t fileno, uid_t uid, int size)
1292 {
1293 	struct cachefs_log_symlink_record *record;
1294 
1295 	/* In Solaris 64 - if can't represent time don't bother */
1296 	RET_IF_TIME_OVERFLOW(cachep, time)
1297 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1298 	if (record == NULL) {
1299 		cachefs_log_error(cachep, ENOMEM, 1);
1300 		return;
1301 	}
1302 
1303 	record->type = CACHEFS_LOG_SYMLINK;
1304 	record->time = time;
1305 
1306 	record->error = Errno;
1307 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1308 	if (fidp != NULL) {
1309 		CACHEFS_FID_COPY(fidp, &record->fid);
1310 	}
1311 	record->fileno = fileno;
1312 	record->uid = uid;
1313 	record->size = size;
1314 
1315 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1316 	    cachefs_xdr_symlink);
1317 }
1318 
1319 static bool_t
1320 cachefs_xdr_symlink(XDR *xdrs, struct cachefs_log_symlink_record *rec)
1321 {
1322 	if ((! xdr_int(xdrs, &rec->type)) ||
1323 	    (! xdr_int(xdrs, &rec->error)) ||
1324 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1325 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1326 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1327 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1328 	    (! xdr_int(xdrs, &rec->uid)) ||
1329 	    (! xdr_u_int(xdrs, &rec->size)))
1330 		return (FALSE);
1331 
1332 	return (TRUE);
1333 }
1334 
1335 void
1336 cachefs_log_populate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1337     fid_t *fidp, ino64_t fileno, u_offset_t off, size_t popsize)
1338 {
1339 	struct cachefs_log_populate_record *record;
1340 
1341 	/* In Solaris 64 - if can't represent time don't bother */
1342 	RET_IF_TIME_OVERFLOW(cachep, time)
1343 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1344 	if (record == NULL) {
1345 		cachefs_log_error(cachep, ENOMEM, 1);
1346 		return;
1347 	}
1348 
1349 	record->type = CACHEFS_LOG_POPULATE;
1350 	record->time = time;
1351 	record->error = Errno;
1352 
1353 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1354 	if (fidp != NULL) {
1355 		CACHEFS_FID_COPY(fidp, &record->fid);
1356 	}
1357 	record->fileno = fileno;
1358 	record->off = off;
1359 	record->size = (int)popsize;
1360 
1361 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1362 	    cachefs_xdr_populate);
1363 }
1364 
1365 static bool_t
1366 cachefs_xdr_populate(XDR *xdrs, struct cachefs_log_populate_record *rec)
1367 {
1368 	if ((! xdr_int(xdrs, &rec->type)) ||
1369 	    (! xdr_int(xdrs, &rec->error)) ||
1370 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1371 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1372 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1373 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1374 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
1375 	    (! xdr_u_int(xdrs, &rec->size)))
1376 		return (FALSE);
1377 
1378 	return (TRUE);
1379 }
1380 
1381 void
1382 cachefs_log_csymlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1383     fid_t *fidp, ino64_t fileno, int size)
1384 {
1385 	struct cachefs_log_csymlink_record *record;
1386 
1387 	/* In Solaris 64 - if can't represent time don't bother */
1388 	RET_IF_TIME_OVERFLOW(cachep, time)
1389 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1390 	if (record == NULL) {
1391 		cachefs_log_error(cachep, ENOMEM, 1);
1392 		return;
1393 	}
1394 
1395 	record->type = CACHEFS_LOG_CSYMLINK;
1396 	record->time = time;
1397 	record->error = Errno;
1398 
1399 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1400 	if (fidp != NULL) {
1401 		CACHEFS_FID_COPY(fidp, &record->fid);
1402 	}
1403 	record->fileno = fileno;
1404 	record->size = size;
1405 
1406 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1407 	    cachefs_xdr_csymlink);
1408 }
1409 
1410 static bool_t
1411 cachefs_xdr_csymlink(XDR *xdrs, struct cachefs_log_csymlink_record *rec)
1412 {
1413 	if ((! xdr_int(xdrs, &rec->type)) ||
1414 	    (! xdr_int(xdrs, &rec->error)) ||
1415 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1416 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1417 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1418 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1419 	    (! xdr_int(xdrs, &rec->size)))
1420 		return (FALSE);
1421 
1422 	return (TRUE);
1423 }
1424 
1425 void
1426 cachefs_log_filldir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1427     fid_t *fidp, ino64_t fileno, u_offset_t size)
1428 {
1429 	struct cachefs_log_filldir_record *record;
1430 
1431 	/* In Solaris 64 - if can't represent time don't bother */
1432 	RET_IF_TIME_OVERFLOW(cachep, time)
1433 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1434 	if (record == NULL) {
1435 		cachefs_log_error(cachep, ENOMEM, 1);
1436 		return;
1437 	}
1438 
1439 	record->type = CACHEFS_LOG_FILLDIR;
1440 	record->time = time;
1441 	record->error = Errno;
1442 
1443 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1444 	if (fidp != NULL) {
1445 		CACHEFS_FID_COPY(fidp, &record->fid);
1446 	}
1447 	record->fileno = fileno;
1448 	record->size = (uint_t)size;
1449 
1450 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1451 	    cachefs_xdr_filldir);
1452 }
1453 
1454 static bool_t
1455 cachefs_xdr_filldir(XDR *xdrs, struct cachefs_log_filldir_record *rec)
1456 {
1457 	if ((! xdr_int(xdrs, &rec->type)) ||
1458 	    (! xdr_int(xdrs, &rec->error)) ||
1459 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1460 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1461 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1462 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1463 	    (! xdr_u_int(xdrs, (uint_t *)&rec->size)))
1464 		return (FALSE);
1465 
1466 	return (TRUE);
1467 }
1468 
1469 void
1470 cachefs_log_mdcreate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1471     fid_t *fidp, ino64_t fileno, uint_t count)
1472 {
1473 	struct cachefs_log_mdcreate_record *record;
1474 
1475 	/* In Solaris 64 - if can't represent time don't bother */
1476 	RET_IF_TIME_OVERFLOW(cachep, time)
1477 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1478 	if (record == NULL) {
1479 		cachefs_log_error(cachep, ENOMEM, 1);
1480 		return;
1481 	}
1482 
1483 	record->type = CACHEFS_LOG_MDCREATE;
1484 	record->time = time;
1485 	record->error = Errno;
1486 
1487 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1488 	if (fidp != NULL) {
1489 		CACHEFS_FID_COPY(fidp, &record->fid);
1490 	}
1491 	record->fileno = fileno;
1492 	record->count = count;
1493 
1494 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1495 	    cachefs_xdr_mdcreate);
1496 }
1497 
1498 static bool_t
1499 cachefs_xdr_mdcreate(XDR *xdrs, struct cachefs_log_mdcreate_record *rec)
1500 {
1501 	if ((! xdr_int(xdrs, &rec->type)) ||
1502 	    (! xdr_int(xdrs, &rec->error)) ||
1503 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1504 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1505 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1506 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1507 	    (! xdr_u_int(xdrs, &rec->count)))
1508 		return (FALSE);
1509 
1510 	return (TRUE);
1511 }
1512 
1513 void
1514 cachefs_log_gpfront(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1515     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, uint_t len)
1516 {
1517 	struct cachefs_log_gpfront_record *record;
1518 
1519 	/* In Solaris 64 - if can't represent time don't bother */
1520 	RET_IF_TIME_OVERFLOW(cachep, time)
1521 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1522 	if (record == NULL) {
1523 		cachefs_log_error(cachep, ENOMEM, 1);
1524 		return;
1525 	}
1526 
1527 	record->type = CACHEFS_LOG_GPFRONT;
1528 	record->time = time;
1529 	record->error = Errno;
1530 
1531 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1532 	if (fidp != NULL) {
1533 		CACHEFS_FID_COPY(fidp, &record->fid);
1534 	}
1535 	record->fileno = fileno;
1536 	record->uid = uid;
1537 	record->off = offset;
1538 	record->len = len;
1539 
1540 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1541 	    cachefs_xdr_gpfront);
1542 }
1543 
1544 static bool_t
1545 cachefs_xdr_gpfront(XDR *xdrs, struct cachefs_log_gpfront_record *rec)
1546 {
1547 	if ((! xdr_int(xdrs, &rec->type)) ||
1548 	    (! xdr_int(xdrs, &rec->error)) ||
1549 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1550 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1551 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1552 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1553 	    (! xdr_int(xdrs, &rec->uid)) ||
1554 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
1555 	    (! xdr_u_int(xdrs, &rec->len)))
1556 		return (FALSE);
1557 
1558 	return (TRUE);
1559 }
1560 
1561 void
1562 cachefs_log_rfdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1563     fid_t *fidp, ino64_t fileno, uid_t uid)
1564 {
1565 	struct cachefs_log_rfdir_record *record;
1566 
1567 	/* In Solaris 64 - if can't represent time don't bother */
1568 	RET_IF_TIME_OVERFLOW(cachep, time)
1569 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1570 	if (record == NULL) {
1571 		cachefs_log_error(cachep, ENOMEM, 1);
1572 		return;
1573 	}
1574 
1575 	record->type = CACHEFS_LOG_RFDIR;
1576 	record->time = time;
1577 	record->error = Errno;
1578 
1579 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1580 	if (fidp != NULL) {
1581 		CACHEFS_FID_COPY(fidp, &record->fid);
1582 	}
1583 	record->fileno = fileno;
1584 	record->uid = uid;
1585 
1586 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1587 	    cachefs_xdr_rfdir);
1588 }
1589 
1590 static bool_t
1591 cachefs_xdr_rfdir(XDR *xdrs, struct cachefs_log_rfdir_record *rec)
1592 {
1593 	if ((! xdr_int(xdrs, &rec->type)) ||
1594 	    (! xdr_int(xdrs, &rec->error)) ||
1595 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1596 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1597 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1598 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1599 	    (! xdr_int(xdrs, &rec->uid)))
1600 		return (FALSE);
1601 
1602 	return (TRUE);
1603 }
1604 
1605 void
1606 cachefs_log_ualloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1607     fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len)
1608 {
1609 	struct cachefs_log_ualloc_record *record;
1610 
1611 	/* In Solaris 64 - if can't represent time don't bother */
1612 	RET_IF_TIME_OVERFLOW(cachep, time)
1613 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1614 	if (record == NULL) {
1615 		cachefs_log_error(cachep, ENOMEM, 1);
1616 		return;
1617 	}
1618 
1619 	record->type = CACHEFS_LOG_UALLOC;
1620 	record->time = time;
1621 	record->error = Errno;
1622 
1623 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1624 	if (fidp != NULL) {
1625 		CACHEFS_FID_COPY(fidp, &record->fid);
1626 	}
1627 	record->fileno = fileno;
1628 	record->off = off;
1629 	record->len = (uint_t)len;
1630 
1631 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1632 	    cachefs_xdr_ualloc);
1633 }
1634 
1635 static bool_t
1636 cachefs_xdr_ualloc(XDR *xdrs, struct cachefs_log_ualloc_record *rec)
1637 {
1638 	if ((! xdr_int(xdrs, &rec->type)) ||
1639 	    (! xdr_int(xdrs, &rec->error)) ||
1640 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1641 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1642 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1643 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1644 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
1645 	    (! xdr_u_int(xdrs, (uint_t *)&rec->len)))
1646 		return (FALSE);
1647 
1648 	return (TRUE);
1649 }
1650 
1651 void
1652 cachefs_log_calloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1653     fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len)
1654 {
1655 	struct cachefs_log_calloc_record *record;
1656 
1657 	/* In Solaris 64 - if can't represent time don't bother */
1658 	RET_IF_TIME_OVERFLOW(cachep, time)
1659 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1660 	if (record == NULL) {
1661 		cachefs_log_error(cachep, ENOMEM, 1);
1662 		return;
1663 	}
1664 
1665 	record->type = CACHEFS_LOG_CALLOC;
1666 	record->time = time;
1667 	record->error = Errno;
1668 
1669 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1670 	if (fidp != NULL) {
1671 		CACHEFS_FID_COPY(fidp, &record->fid);
1672 	}
1673 	record->fileno = fileno;
1674 	record->off = off;
1675 	record->len = (uint_t)len;
1676 
1677 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1678 	    cachefs_xdr_calloc);
1679 }
1680 
1681 static bool_t
1682 cachefs_xdr_calloc(XDR *xdrs, struct cachefs_log_calloc_record *rec)
1683 {
1684 	if ((! xdr_int(xdrs, &rec->type)) ||
1685 	    (! xdr_int(xdrs, &rec->error)) ||
1686 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1687 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1688 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1689 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
1690 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
1691 	    (! xdr_u_int(xdrs, &rec->len)))
1692 		return (FALSE);
1693 
1694 	return (TRUE);
1695 }
1696 
1697 void
1698 cachefs_log_nocache(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
1699     fid_t *fidp, ino64_t fileno)
1700 {
1701 	struct cachefs_log_nocache_record *record;
1702 
1703 	/* In Solaris 64 - if can't represent time don't bother */
1704 	RET_IF_TIME_OVERFLOW(cachep, time)
1705 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
1706 	if (record == NULL) {
1707 		cachefs_log_error(cachep, ENOMEM, 1);
1708 		return;
1709 	}
1710 
1711 	record->type = CACHEFS_LOG_NOCACHE;
1712 	record->time = time;
1713 	record->error = Errno;
1714 
1715 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
1716 	if (fidp != NULL) {
1717 		CACHEFS_FID_COPY(fidp, &record->fid);
1718 	}
1719 	record->fileno = fileno;
1720 
1721 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
1722 	    cachefs_xdr_nocache);
1723 
1724 }
1725 
1726 static bool_t
1727 cachefs_xdr_nocache(XDR *xdrs, struct cachefs_log_nocache_record *rec)
1728 {
1729 	if ((! xdr_int(xdrs, &rec->type)) ||
1730 	    (! xdr_int(xdrs, &rec->error)) ||
1731 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
1732 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
1733 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
1734 	    (! xdr_ino64(xdrs, &rec->fileno)))
1735 		return (FALSE);
1736 
1737 	return (TRUE);
1738 }
1739