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