Home | History | Annotate | Download | only in cachefs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <sys/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 explicitly
     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, NULL,
    202 		    0);
    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, NULL, NULL, NULL)) != 0) &&
    251 	    ((error = VOP_CREATE(cachep->c_dirvp, LOG_STATUS_NAME, &attr, EXCL,
    252 	    0600, &savevp, kcred, 0, NULL, NULL)) != 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 occurred.
    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 occurred 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, NULL,
    442 		    0);
    443 
    444 	if (getlock)
    445 		mutex_exit(&cachep->c_log_mutex);
    446 }
    447 
    448 static int
    449 cachefs_log_write_header(struct vnode *vp, cachefscache_t *cachep, int error)
    450 {
    451 	struct cachefs_log_logfile_header header, oheader;
    452 	char buffy[2 * sizeof (header)];
    453 	int Errno = 0;
    454 	struct vattr attr;
    455 	int gotold = 0;
    456 	XDR xdrm;
    457 
    458 	attr.va_mask = AT_SIZE;
    459 	if ((error = VOP_GETATTR(vp, &attr, 0, kcred, NULL)) != 0)
    460 		goto out;
    461 	if (attr.va_size != 0) {
    462 		error = vn_rdwr(UIO_READ, vp, buffy,
    463 		    MIN(sizeof (buffy), attr.va_size),
    464 		    0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
    465 		if (error != 0)
    466 			goto out;
    467 
    468 		xdrm.x_ops = NULL;
    469 		xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_DECODE);
    470 		if ((xdrm.x_ops == NULL) ||
    471 		    (! cachefs_xdr_logfile_header(&xdrm, &oheader))) {
    472 			if (xdrm.x_ops != NULL)
    473 				xdr_destroy(&xdrm);
    474 			error = EINVAL;
    475 			goto out;
    476 		}
    477 		xdr_destroy(&xdrm);
    478 		gotold = 1;
    479 
    480 		if (oheader.lh_magic != CACHEFS_LOG_MAGIC) {
    481 			error = EINVAL;
    482 			goto out;
    483 		}
    484 	}
    485 
    486 	xdrm.x_ops = NULL;
    487 
    488 	xdrmem_create(&xdrm, buffy, sizeof (buffy), XDR_ENCODE);
    489 
    490 	if (gotold) {
    491 		header = oheader;
    492 	} else {
    493 		header.lh_magic = CACHEFS_LOG_MAGIC;
    494 		header.lh_revision = CACHEFS_LOG_FILE_REV;
    495 		header.lh_blocks = cachep->c_usage.cu_blksused;
    496 		header.lh_files = cachep->c_usage.cu_filesused;
    497 		header.lh_maxbsize = MAXBSIZE;
    498 		header.lh_pagesize = PAGESIZE;
    499 	}
    500 
    501 	/* these are things that we stomp over for every header write */
    502 	header.lh_errno = Errno;
    503 
    504 	if (! cachefs_xdr_logfile_header(&xdrm, &header)) {
    505 		error = ENOMEM;
    506 		goto out;
    507 	}
    508 
    509 	error = vn_rdwr(UIO_WRITE, vp,
    510 	    (caddr_t)buffy, xdr_getpos(&xdrm),
    511 	    0LL, UIO_SYSSPACE, FSYNC, (rlim64_t)RLIM_INFINITY, kcred, NULL);
    512 	if (error)
    513 		goto out;
    514 
    515 out:
    516 	if (xdrm.x_ops != NULL)
    517 		xdr_destroy(&xdrm);
    518 	return (error);
    519 }
    520 
    521 /*
    522  * enqueues a record to be written to the logfile.
    523  */
    524 
    525 static void
    526 cachefs_log_enqueue(cachefscache_t *cachep, void *record, int size,
    527     xdrproc_t translate)
    528 {
    529 	cachefs_log_cookie_t *cl;
    530 	cachefs_log_work_list_t newnode, oldnode;
    531 
    532 	mutex_enter(&cachep->c_log_mutex);
    533 	cl = cachep->c_log;
    534 
    535 	if (cl == NULL) { /* someone turned off logging out from under us */
    536 		mutex_exit(&cachep->c_log_mutex);
    537 		cachefs_kmem_free(record, size);
    538 		return;
    539 	}
    540 	ASSERT(cl->cl_magic == CACHEFS_LOG_MAGIC);
    541 
    542 	cl->cl_size += size;
    543 	newnode = cachefs_kmem_zalloc(sizeof (*newnode), KM_NOSLEEP);
    544 	if ((cl->cl_size > CACHEFS_LOG_MAX_BUFFERED) || (newnode == NULL)) {
    545 		cachefs_log_error(cachep, ENOMEM, 0);
    546 		if (newnode != NULL)
    547 			cachefs_kmem_free(newnode, sizeof (*newnode));
    548 		cachefs_kmem_free(record, size);
    549 		mutex_exit(&cachep->c_log_mutex);
    550 		return;
    551 	}
    552 
    553 	newnode->data = record;
    554 	newnode->size = size;
    555 	newnode->translate = translate;
    556 	newnode->next = NULL;
    557 
    558 	oldnode = (cachefs_log_work_list_t)cl->cl_tail;
    559 	if (oldnode != NULL)
    560 		oldnode->next = newnode;
    561 	cl->cl_tail = newnode;
    562 	if (cl->cl_head == NULL)
    563 		cl->cl_head = newnode;
    564 	mutex_exit(&cachep->c_log_mutex);
    565 
    566 	if (cl->cl_size >= CACHEFS_LOG_LOWATER) {
    567 		mutex_enter(&cachep->c_workq.wq_queue_lock);
    568 		cachep->c_workq.wq_logwork = 1;
    569 		cv_signal(&cachep->c_workq.wq_req_cv);
    570 		mutex_exit(&cachep->c_workq.wq_queue_lock);
    571 	}
    572 }
    573 
    574 /*
    575  * processes the log queue.  run by an async worker thread, or via
    576  * cachefs_cache_sync().
    577  */
    578 
    579 void
    580 cachefs_log_process_queue(cachefscache_t *cachep, int getlock)
    581 {
    582 	cachefs_log_cookie_t *cl;
    583 	cachefs_log_work_list_t work, workhead, oldwork;
    584 	struct vnode *logvp = NULL;
    585 	struct uio uio;
    586 	struct iovec iov;
    587 	int error = 0;
    588 	XDR xdrm;
    589 	char *buffy = NULL;
    590 
    591 	/*
    592 	 * NULL out the x_ops field of XDR.  this way, if x_ops !=
    593 	 * NULL, we know that we did the xdr*_create() successfully.
    594 	 * this is documented in the xdr_create man page.
    595 	 */
    596 
    597 	xdrm.x_ops = NULL;
    598 
    599 	/* see if we're still logging */
    600 	if (getlock)
    601 		mutex_enter(&cachep->c_log_mutex);
    602 	cl = cachep->c_log;
    603 	if ((cl == NULL) || (cl->cl_magic != CACHEFS_LOG_MAGIC)) {
    604 		if (getlock)
    605 			mutex_exit(&cachep->c_log_mutex);
    606 		return;
    607 	}
    608 
    609 	/* get the work, and let go of the mutex asap. */
    610 	workhead = cl->cl_head;
    611 	cl->cl_head = cl->cl_tail = NULL;
    612 	cl->cl_size = 0;
    613 	logvp = cl->cl_logvp;
    614 	ASSERT(logvp != NULL);
    615 	if (logvp == NULL) {
    616 		if (getlock)
    617 			mutex_exit(&cachep->c_log_mutex);
    618 		return;
    619 	}
    620 	VN_HOLD(logvp);
    621 	if (getlock)
    622 		mutex_exit(&cachep->c_log_mutex);
    623 
    624 	/* we don't use vn_rdwr() because there's no way to set FNONBLOCK */
    625 
    626 	uio.uio_iov = &iov;
    627 	uio.uio_iovcnt = 1;
    628 	uio.uio_loffset = 0; /* fake -- we do FAPPEND */
    629 	uio.uio_segflg = (short)UIO_SYSSPACE;
    630 	uio.uio_llimit = MAXOFFSET_T;
    631 	uio.uio_fmode = FWRITE | FNONBLOCK;
    632 	uio.uio_extflg = UIO_COPY_CACHED;
    633 
    634 	buffy = cachefs_kmem_alloc(CACHEFS_LOG_ENCODE_SIZE, KM_SLEEP);
    635 	xdrmem_create(&xdrm, buffy, CACHEFS_LOG_ENCODE_SIZE, XDR_ENCODE);
    636 
    637 	(void) VOP_RWLOCK(logvp, V_WRITELOCK_TRUE, NULL);
    638 	for (work = workhead; work != NULL; work = work->next) {
    639 		if (! (work->translate)(&xdrm, work->data)) {
    640 			VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
    641 			error = ENOMEM;
    642 			goto out;
    643 		}
    644 
    645 		iov.iov_base = buffy;
    646 		iov.iov_len = uio.uio_resid = xdr_getpos(&xdrm);
    647 		(void) xdr_setpos(&xdrm, 0);
    648 
    649 		error = VOP_WRITE(logvp, &uio, FAPPEND, kcred, NULL);
    650 
    651 		/* XXX future -- check for EAGAIN */
    652 
    653 		if ((error) || (uio.uio_resid)) {
    654 			if (uio.uio_resid != 0)
    655 				error = EIO;
    656 			VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
    657 			goto out;
    658 		}
    659 	}
    660 	VOP_RWUNLOCK(logvp, V_WRITELOCK_TRUE, NULL);
    661 
    662 out:
    663 	if (xdrm.x_ops != NULL)
    664 		xdr_destroy(&xdrm);
    665 	if (buffy != NULL)
    666 		cachefs_kmem_free(buffy, CACHEFS_LOG_ENCODE_SIZE);
    667 
    668 	/*
    669 	 * if an error occurred, we need to free the buffers ourselves.
    670 	 * cachefs_destory_cookie() can't do it.
    671 	 */
    672 
    673 	work = workhead;
    674 	while (work != NULL) {
    675 		cachefs_kmem_free(work->data, work->size);
    676 		oldwork = work;
    677 		work = work->next;
    678 		cachefs_kmem_free(oldwork, sizeof (*oldwork));
    679 	}
    680 	if (logvp != NULL)
    681 		VN_RELE(logvp);
    682 	if (error) {
    683 		cachefs_log_error(cachep, error, 1);
    684 		return;
    685 	}
    686 }
    687 
    688 static bool_t
    689 cachefs_xdr_logfile_header(XDR *xdrs, struct cachefs_log_logfile_header *h)
    690 {
    691 	if ((! xdr_u_int(xdrs, &h->lh_magic)) ||
    692 	    (! xdr_u_int(xdrs, &h->lh_revision)) ||
    693 	    (! xdr_int(xdrs, &h->lh_errno)) ||
    694 	    (! xdr_u_int(xdrs, &h->lh_blocks)) ||
    695 	    (! xdr_u_int(xdrs, &h->lh_files)) ||
    696 	    (! xdr_u_int(xdrs, &h->lh_maxbsize)) ||
    697 	    (! xdr_u_int(xdrs, &h->lh_pagesize)))
    698 		return (FALSE);
    699 
    700 	return (TRUE);
    701 }
    702 
    703 /*
    704  * the routines for logging each transaction follow...
    705  */
    706 
    707 void
    708 cachefs_log_mount(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
    709     fscache_t *fscp, char *upath, enum uio_seg seg, char *cacheid)
    710 {
    711 	struct cachefs_log_mount_record *record;
    712 	char *cacheidt;
    713 	char *path = NULL;
    714 	size_t len;
    715 	int len1, len2;
    716 	int size, error;
    717 
    718 	/* In Solaris 64 - if can't represent time don't bother */
    719 	OUT_IF_TIME_OVERFLOW(cachep, time)
    720 	if (seg == UIO_USERSPACE) {
    721 		path = cachefs_kmem_alloc(MAXPATHLEN, KM_NOSLEEP);
    722 		if (path == NULL) {
    723 			cachefs_log_error(cachep, ENOMEM, 1);
    724 			goto out;
    725 		}
    726 		if ((error = copyinstr(upath, path, MAXPATHLEN, &len)) != 0) {
    727 			cachefs_log_error(cachep, error, 1);
    728 			goto out;
    729 		}
    730 	} else {
    731 		path = upath;
    732 	}
    733 
    734 	len1 = (path != NULL) ? strlen(path) : 0;
    735 	len2 = (cacheid != NULL) ? strlen(cacheid) : 0;
    736 	size = (int)sizeof (*record) + len1 + len2 -
    737 	    (int)CLPAD(cachefs_log_mount_record, path);
    738 	record = cachefs_kmem_zalloc(size, KM_NOSLEEP);
    739 	if (record == NULL) {
    740 		cachefs_log_error(cachep, ENOMEM, 1);
    741 		goto out;
    742 	}
    743 
    744 	record->type = CACHEFS_LOG_MOUNT;
    745 	record->time = time;
    746 
    747 	record->error = Errno;
    748 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
    749 
    750 	if (fscp) {
    751 		record->flags = fscp->fs_info.fi_mntflags;
    752 		record->popsize = fscp->fs_info.fi_popsize;
    753 		record->fgsize = fscp->fs_info.fi_fgsize;
    754 	}
    755 
    756 	record->pathlen = (ushort_t)len1;
    757 	record->cacheidlen = (ushort_t)len2;
    758 	if (path != NULL)
    759 		(void) strcpy(record->path, path);
    760 	cacheidt = record->path + len1 + 1;
    761 	if (cacheid != NULL)
    762 		(void) strcpy(cacheidt, cacheid);
    763 
    764 	cachefs_log_enqueue(cachep, record, size, cachefs_xdr_mount);
    765 
    766 out:
    767 	if ((seg == UIO_USERSPACE) && (path != NULL))
    768 		cachefs_kmem_free(path, MAXPATHLEN);
    769 }
    770 
    771 static bool_t
    772 cachefs_xdr_mount(XDR *xdrs, struct cachefs_log_mount_record *rec)
    773 {
    774 	char *path = rec->path;
    775 	char *cacheid;
    776 
    777 	cacheid = path + strlen(path) + 1;
    778 
    779 	if ((! xdr_int(xdrs, &rec->type)) ||
    780 	    (! xdr_int(xdrs, &rec->error)) ||
    781 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
    782 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
    783 	    (! xdr_u_int(xdrs, &rec->flags)) ||
    784 	    (! xdr_u_int(xdrs, &rec->popsize)) ||
    785 	    (! xdr_u_int(xdrs, &rec->fgsize)) ||
    786 	    (! xdr_u_short(xdrs, &rec->pathlen)) ||
    787 	    (! xdr_u_short(xdrs, &rec->cacheidlen)) ||
    788 	    (! xdr_wrapstring(xdrs, &path)) ||
    789 	    (! xdr_wrapstring(xdrs, &cacheid)))
    790 		return (FALSE);
    791 
    792 	return (TRUE);
    793 }
    794 
    795 void
    796 cachefs_log_umount(cachefscache_t *cachep, int Errno, struct vfs *vfsp)
    797 {
    798 	struct cachefs_log_umount_record *record;
    799 
    800 	/* In Solaris 64 - if can't represent time don't bother */
    801 	RET_IF_TIME_OVERFLOW(cachep, time)
    802 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
    803 	if (record == NULL) {
    804 		cachefs_log_error(cachep, ENOMEM, 1);
    805 		return;
    806 	}
    807 
    808 	record->type = CACHEFS_LOG_UMOUNT;
    809 	record->time = time;
    810 
    811 	record->error = Errno;
    812 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
    813 
    814 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
    815 	    cachefs_xdr_umount);
    816 }
    817 
    818 static bool_t
    819 cachefs_xdr_umount(XDR *xdrs, struct cachefs_log_umount_record *rec)
    820 {
    821 	if ((! xdr_int(xdrs, &rec->type)) ||
    822 	    (! xdr_int(xdrs, &rec->error)) ||
    823 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
    824 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))))
    825 		return (FALSE);
    826 
    827 	return (TRUE);
    828 }
    829 
    830 void
    831 cachefs_log_getpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
    832     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len)
    833 {
    834 	struct cachefs_log_getpage_record *record;
    835 
    836 	/* In Solaris 64 - if can't represent time don't bother */
    837 	RET_IF_TIME_OVERFLOW(cachep, time)
    838 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
    839 	if (record == NULL) {
    840 		cachefs_log_error(cachep, ENOMEM, 1);
    841 		return;
    842 	}
    843 
    844 	record->type = CACHEFS_LOG_GETPAGE;
    845 	record->time = time;
    846 
    847 	record->error = Errno;
    848 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
    849 	if (fidp != NULL) {
    850 		CACHEFS_FID_COPY(fidp, &record->fid);
    851 	}
    852 	record->fileno = fileno;
    853 	record->uid = uid;
    854 	record->offset = offset;
    855 	record->len = (uint_t)len;
    856 
    857 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
    858 	    cachefs_xdr_getpage);
    859 }
    860 
    861 static bool_t
    862 cachefs_xdr_getpage(XDR *xdrs, struct cachefs_log_getpage_record *rec)
    863 {
    864 	if ((! xdr_int(xdrs, &rec->type)) ||
    865 	    (! xdr_int(xdrs, &rec->error)) ||
    866 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
    867 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
    868 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
    869 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
    870 	    (! xdr_u_int(xdrs, &rec->uid)) ||
    871 	    (! xdr_u_longlong_t(xdrs, &rec->offset)) ||
    872 	    (! xdr_u_int(xdrs, &rec->len)))
    873 		return (FALSE);
    874 
    875 	return (TRUE);
    876 }
    877 
    878 void
    879 cachefs_log_readdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
    880     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, int eof)
    881 {
    882 	struct cachefs_log_readdir_record *record;
    883 
    884 	/* In Solaris 64 - if can't represent time don't bother */
    885 	RET_IF_TIME_OVERFLOW(cachep, time)
    886 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
    887 	if (record == NULL) {
    888 		cachefs_log_error(cachep, ENOMEM, 1);
    889 		return;
    890 	}
    891 
    892 	record->type = CACHEFS_LOG_READDIR;
    893 	record->time = time;
    894 
    895 	record->error = Errno;
    896 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
    897 	if (fidp != NULL) {
    898 		CACHEFS_FID_COPY(fidp, &record->fid);
    899 	}
    900 	record->fileno = fileno;
    901 	record->uid = uid;
    902 	record->offset = offset;
    903 	record->eof = eof;
    904 
    905 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
    906 	    cachefs_xdr_readdir);
    907 }
    908 
    909 static bool_t
    910 cachefs_xdr_readdir(XDR *xdrs, struct cachefs_log_readdir_record *rec)
    911 {
    912 	if ((! xdr_int(xdrs, &rec->type)) ||
    913 	    (! xdr_int(xdrs, &rec->error)) ||
    914 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
    915 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
    916 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
    917 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
    918 	    (! xdr_u_int(xdrs, &rec->uid)) ||
    919 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) ||
    920 	    (! xdr_int(xdrs, &rec->eof)))
    921 		return (FALSE);
    922 
    923 	return (TRUE);
    924 }
    925 
    926 void
    927 cachefs_log_readlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
    928     fid_t *fidp, ino64_t fileno, uid_t uid, size_t length)
    929 {
    930 	struct cachefs_log_readlink_record *record;
    931 
    932 	/* In Solaris 64 - if can't represent time don't bother */
    933 	RET_IF_TIME_OVERFLOW(cachep, time)
    934 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
    935 	if (record == NULL) {
    936 		cachefs_log_error(cachep, ENOMEM, 1);
    937 		return;
    938 	}
    939 
    940 	record->type = CACHEFS_LOG_READLINK;
    941 	record->time = time;
    942 
    943 	record->error = Errno;
    944 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
    945 	if (fidp != NULL) {
    946 		CACHEFS_FID_COPY(fidp, &record->fid);
    947 	}
    948 	record->fileno = fileno;
    949 	record->uid = uid;
    950 	record->length = (uint_t)length;
    951 
    952 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
    953 	    cachefs_xdr_readlink);
    954 }
    955 
    956 static bool_t
    957 cachefs_xdr_readlink(XDR *xdrs, struct cachefs_log_readlink_record *rec)
    958 {
    959 	if ((! xdr_int(xdrs, &rec->type)) ||
    960 	    (! xdr_int(xdrs, &rec->error)) ||
    961 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
    962 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
    963 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
    964 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
    965 	    (! xdr_u_int(xdrs, &rec->uid)) ||
    966 	    (! xdr_u_int(xdrs, &rec->length)))
    967 		return (FALSE);
    968 
    969 	return (TRUE);
    970 }
    971 
    972 void
    973 cachefs_log_remove(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
    974     fid_t *fidp, ino64_t fileno, uid_t uid)
    975 {
    976 	struct cachefs_log_remove_record *record;
    977 
    978 	/* In Solaris 64 - if can't represent time don't bother */
    979 	RET_IF_TIME_OVERFLOW(cachep, time)
    980 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
    981 	if (record == NULL) {
    982 		cachefs_log_error(cachep, ENOMEM, 1);
    983 		return;
    984 	}
    985 
    986 	record->type = CACHEFS_LOG_REMOVE;
    987 	record->time = time;
    988 
    989 	record->error = Errno;
    990 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
    991 	if (fidp != NULL) {
    992 		CACHEFS_FID_COPY(fidp, &record->fid);
    993 	}
    994 	record->fileno = fileno;
    995 	record->uid = uid;
    996 
    997 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
    998 	    cachefs_xdr_remove);
    999 }
   1000 
   1001 static bool_t
   1002 cachefs_xdr_remove(XDR *xdrs, struct cachefs_log_remove_record *rec)
   1003 {
   1004 	if ((! xdr_int(xdrs, &rec->type)) ||
   1005 	    (! xdr_int(xdrs, &rec->error)) ||
   1006 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1007 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1008 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1009 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1010 	    (! xdr_u_int(xdrs, &rec->uid)))
   1011 		return (FALSE);
   1012 
   1013 	return (TRUE);
   1014 }
   1015 
   1016 void
   1017 cachefs_log_rmdir(cachefscache_t *cachep, int Errno,
   1018     struct vfs *vfsp, fid_t *fidp, ino64_t fileno, uid_t uid)
   1019 {
   1020 	struct cachefs_log_rmdir_record *record;
   1021 
   1022 	/* In Solaris 64 - if can't represent time don't bother */
   1023 	RET_IF_TIME_OVERFLOW(cachep, time)
   1024 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1025 	if (record == NULL) {
   1026 		cachefs_log_error(cachep, ENOMEM, 1);
   1027 		return;
   1028 	}
   1029 
   1030 	record->type = CACHEFS_LOG_RMDIR;
   1031 	record->time = time;
   1032 
   1033 	record->error = Errno;
   1034 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1035 	if (fidp != NULL) {
   1036 		CACHEFS_FID_COPY(fidp, &record->fid);
   1037 	}
   1038 	record->fileno = fileno;
   1039 	record->uid = uid;
   1040 
   1041 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1042 	    cachefs_xdr_rmdir);
   1043 }
   1044 
   1045 static bool_t
   1046 cachefs_xdr_rmdir(XDR *xdrs, struct cachefs_log_rmdir_record *rec)
   1047 {
   1048 	if ((! xdr_int(xdrs, &rec->type)) ||
   1049 	    (! xdr_int(xdrs, &rec->error)) ||
   1050 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1051 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1052 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1053 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1054 	    (! xdr_u_int(xdrs, &rec->uid)))
   1055 		return (FALSE);
   1056 
   1057 	return (TRUE);
   1058 }
   1059 
   1060 void
   1061 cachefs_log_truncate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1062     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t size)
   1063 {
   1064 	struct cachefs_log_truncate_record *record;
   1065 
   1066 	/* In Solaris 64 - if can't represent time don't bother */
   1067 	RET_IF_TIME_OVERFLOW(cachep, time)
   1068 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1069 	if (record == NULL) {
   1070 		cachefs_log_error(cachep, ENOMEM, 1);
   1071 		return;
   1072 	}
   1073 
   1074 	record->type = CACHEFS_LOG_TRUNCATE;
   1075 	record->time = time;
   1076 
   1077 	record->error = Errno;
   1078 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1079 	if (fidp != NULL) {
   1080 		CACHEFS_FID_COPY(fidp, &record->fid);
   1081 	}
   1082 	record->fileno = fileno;
   1083 	record->uid = uid;
   1084 	record->size = size;
   1085 
   1086 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1087 	    cachefs_xdr_truncate);
   1088 }
   1089 
   1090 static bool_t
   1091 cachefs_xdr_truncate(XDR *xdrs, struct cachefs_log_truncate_record *rec)
   1092 {
   1093 	if ((! xdr_int(xdrs, &rec->type)) ||
   1094 	    (! xdr_int(xdrs, &rec->error)) ||
   1095 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1096 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1097 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1098 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1099 	    (! xdr_u_int(xdrs, &rec->uid)) ||
   1100 	    (! xdr_u_longlong_t(xdrs, &rec->size)))
   1101 		return (FALSE);
   1102 
   1103 	return (TRUE);
   1104 }
   1105 
   1106 void
   1107 cachefs_log_putpage(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1108     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, size_t len)
   1109 {
   1110 	struct cachefs_log_putpage_record *record;
   1111 
   1112 	/* In Solaris 64 - if can't represent time don't bother */
   1113 	RET_IF_TIME_OVERFLOW(cachep, time)
   1114 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1115 	if (record == NULL) {
   1116 		cachefs_log_error(cachep, ENOMEM, 1);
   1117 		return;
   1118 	}
   1119 
   1120 	record->type = CACHEFS_LOG_PUTPAGE;
   1121 	record->time = time;
   1122 
   1123 	record->error = Errno;
   1124 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1125 	if (fidp != NULL) {
   1126 		CACHEFS_FID_COPY(fidp, &record->fid);
   1127 	}
   1128 	record->fileno = fileno;
   1129 	record->uid = uid;
   1130 	record->offset = offset;
   1131 	record->len = (uint_t)len;
   1132 
   1133 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1134 	    cachefs_xdr_putpage);
   1135 }
   1136 
   1137 static bool_t
   1138 cachefs_xdr_putpage(XDR *xdrs, struct cachefs_log_putpage_record *rec)
   1139 {
   1140 	if ((! xdr_int(xdrs, &rec->type)) ||
   1141 	    (! xdr_int(xdrs, &rec->error)) ||
   1142 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1143 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1144 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1145 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1146 	    (! xdr_u_int(xdrs, &rec->uid)) ||
   1147 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->offset)) ||
   1148 	    (! xdr_u_int(xdrs, &rec->len)))
   1149 		return (FALSE);
   1150 
   1151 	return (TRUE);
   1152 }
   1153 
   1154 void
   1155 cachefs_log_create(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1156     fid_t *filefidp, ino64_t fileno, uid_t uid)
   1157 {
   1158 	struct cachefs_log_create_record *record;
   1159 
   1160 	/* In Solaris 64 - if can't represent time don't bother */
   1161 	RET_IF_TIME_OVERFLOW(cachep, time)
   1162 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1163 	if (record == NULL) {
   1164 		cachefs_log_error(cachep, ENOMEM, 1);
   1165 		return;
   1166 	}
   1167 
   1168 	record->type = CACHEFS_LOG_CREATE;
   1169 	record->time = time;
   1170 
   1171 	record->error = Errno;
   1172 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1173 	if (filefidp != NULL) {
   1174 		CACHEFS_FID_COPY(filefidp, &record->fid);
   1175 	}
   1176 	record->fileno = fileno;
   1177 	record->uid = uid;
   1178 
   1179 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1180 	    cachefs_xdr_create);
   1181 }
   1182 
   1183 static bool_t
   1184 cachefs_xdr_create(XDR *xdrs, struct cachefs_log_create_record *rec)
   1185 {
   1186 	if ((! xdr_int(xdrs, &rec->type)) ||
   1187 	    (! xdr_int(xdrs, &rec->error)) ||
   1188 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1189 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1190 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1191 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1192 	    (! xdr_u_int(xdrs, &rec->uid)))
   1193 		return (FALSE);
   1194 
   1195 	return (TRUE);
   1196 }
   1197 
   1198 void
   1199 cachefs_log_mkdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1200     fid_t *cfidp, ino64_t fileno, uid_t uid)
   1201 {
   1202 	struct cachefs_log_mkdir_record *record;
   1203 	int size;
   1204 
   1205 	/* In Solaris 64 - if can't represent time don't bother */
   1206 	RET_IF_TIME_OVERFLOW(cachep, time)
   1207 	size = (int)sizeof (*record);
   1208 	record = cachefs_kmem_zalloc(size, KM_NOSLEEP);
   1209 	if (record == NULL) {
   1210 		cachefs_log_error(cachep, ENOMEM, 1);
   1211 		return;
   1212 	}
   1213 
   1214 	record->type = CACHEFS_LOG_MKDIR;
   1215 	record->time = time;
   1216 
   1217 	record->error = Errno;
   1218 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1219 	if (cfidp != NULL) {
   1220 		CACHEFS_FID_COPY(cfidp, &record->fid);
   1221 	}
   1222 	record->fileno = fileno;
   1223 	record->uid = uid;
   1224 
   1225 	cachefs_log_enqueue(cachep, record, size,
   1226 	    cachefs_xdr_mkdir);
   1227 }
   1228 
   1229 static bool_t
   1230 cachefs_xdr_mkdir(XDR *xdrs, struct cachefs_log_mkdir_record *rec)
   1231 {
   1232 	if ((! xdr_int(xdrs, &rec->type)) ||
   1233 	    (! xdr_int(xdrs, &rec->error)) ||
   1234 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1235 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1236 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1237 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1238 	    (! xdr_u_int(xdrs, &rec->uid)))
   1239 		return (FALSE);
   1240 
   1241 	return (TRUE);
   1242 }
   1243 
   1244 void
   1245 cachefs_log_rename(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1246     fid_t *gfp, ino64_t fileno, int removed, uid_t uid)
   1247 {
   1248 	struct cachefs_log_rename_record *record;
   1249 
   1250 	/* In Solaris 64 - if can't represent time don't bother */
   1251 	RET_IF_TIME_OVERFLOW(cachep, time)
   1252 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1253 	if (record == NULL) {
   1254 		cachefs_log_error(cachep, ENOMEM, 1);
   1255 		return;
   1256 	}
   1257 
   1258 	record->type = CACHEFS_LOG_RENAME;
   1259 	record->time = time;
   1260 
   1261 	record->error = Errno;
   1262 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1263 	if (gfp != NULL) {
   1264 		CACHEFS_FID_COPY(gfp, &record->gone);
   1265 	}
   1266 	record->fileno = fileno;
   1267 	record->removed = removed;
   1268 	record->uid = uid;
   1269 
   1270 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1271 	    cachefs_xdr_rename);
   1272 }
   1273 
   1274 static bool_t
   1275 cachefs_xdr_rename(XDR *xdrs, struct cachefs_log_rename_record *rec)
   1276 {
   1277 	if ((! xdr_int(xdrs, &rec->type)) ||
   1278 	    (! xdr_int(xdrs, &rec->error)) ||
   1279 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1280 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1281 	    (! xdr_opaque(xdrs, (caddr_t)&rec->gone, sizeof (rec->gone))) ||
   1282 	    (! xdr_int(xdrs, &rec->removed)) ||
   1283 	    (! xdr_u_int(xdrs, &rec->uid)))
   1284 		return (FALSE);
   1285 
   1286 	return (TRUE);
   1287 }
   1288 
   1289 
   1290 void
   1291 cachefs_log_symlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1292     fid_t *fidp, ino64_t fileno, uid_t uid, int size)
   1293 {
   1294 	struct cachefs_log_symlink_record *record;
   1295 
   1296 	/* In Solaris 64 - if can't represent time don't bother */
   1297 	RET_IF_TIME_OVERFLOW(cachep, time)
   1298 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1299 	if (record == NULL) {
   1300 		cachefs_log_error(cachep, ENOMEM, 1);
   1301 		return;
   1302 	}
   1303 
   1304 	record->type = CACHEFS_LOG_SYMLINK;
   1305 	record->time = time;
   1306 
   1307 	record->error = Errno;
   1308 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1309 	if (fidp != NULL) {
   1310 		CACHEFS_FID_COPY(fidp, &record->fid);
   1311 	}
   1312 	record->fileno = fileno;
   1313 	record->uid = uid;
   1314 	record->size = size;
   1315 
   1316 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1317 	    cachefs_xdr_symlink);
   1318 }
   1319 
   1320 static bool_t
   1321 cachefs_xdr_symlink(XDR *xdrs, struct cachefs_log_symlink_record *rec)
   1322 {
   1323 	if ((! xdr_int(xdrs, &rec->type)) ||
   1324 	    (! xdr_int(xdrs, &rec->error)) ||
   1325 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1326 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1327 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1328 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1329 	    (! xdr_u_int(xdrs, &rec->uid)) ||
   1330 	    (! xdr_u_int(xdrs, &rec->size)))
   1331 		return (FALSE);
   1332 
   1333 	return (TRUE);
   1334 }
   1335 
   1336 void
   1337 cachefs_log_populate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1338     fid_t *fidp, ino64_t fileno, u_offset_t off, size_t popsize)
   1339 {
   1340 	struct cachefs_log_populate_record *record;
   1341 
   1342 	/* In Solaris 64 - if can't represent time don't bother */
   1343 	RET_IF_TIME_OVERFLOW(cachep, time)
   1344 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1345 	if (record == NULL) {
   1346 		cachefs_log_error(cachep, ENOMEM, 1);
   1347 		return;
   1348 	}
   1349 
   1350 	record->type = CACHEFS_LOG_POPULATE;
   1351 	record->time = time;
   1352 	record->error = Errno;
   1353 
   1354 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1355 	if (fidp != NULL) {
   1356 		CACHEFS_FID_COPY(fidp, &record->fid);
   1357 	}
   1358 	record->fileno = fileno;
   1359 	record->off = off;
   1360 	record->size = (int)popsize;
   1361 
   1362 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1363 	    cachefs_xdr_populate);
   1364 }
   1365 
   1366 static bool_t
   1367 cachefs_xdr_populate(XDR *xdrs, struct cachefs_log_populate_record *rec)
   1368 {
   1369 	if ((! xdr_int(xdrs, &rec->type)) ||
   1370 	    (! xdr_int(xdrs, &rec->error)) ||
   1371 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1372 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1373 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1374 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1375 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
   1376 	    (! xdr_u_int(xdrs, &rec->size)))
   1377 		return (FALSE);
   1378 
   1379 	return (TRUE);
   1380 }
   1381 
   1382 void
   1383 cachefs_log_csymlink(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1384     fid_t *fidp, ino64_t fileno, int size)
   1385 {
   1386 	struct cachefs_log_csymlink_record *record;
   1387 
   1388 	/* In Solaris 64 - if can't represent time don't bother */
   1389 	RET_IF_TIME_OVERFLOW(cachep, time)
   1390 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1391 	if (record == NULL) {
   1392 		cachefs_log_error(cachep, ENOMEM, 1);
   1393 		return;
   1394 	}
   1395 
   1396 	record->type = CACHEFS_LOG_CSYMLINK;
   1397 	record->time = time;
   1398 	record->error = Errno;
   1399 
   1400 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1401 	if (fidp != NULL) {
   1402 		CACHEFS_FID_COPY(fidp, &record->fid);
   1403 	}
   1404 	record->fileno = fileno;
   1405 	record->size = size;
   1406 
   1407 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1408 	    cachefs_xdr_csymlink);
   1409 }
   1410 
   1411 static bool_t
   1412 cachefs_xdr_csymlink(XDR *xdrs, struct cachefs_log_csymlink_record *rec)
   1413 {
   1414 	if ((! xdr_int(xdrs, &rec->type)) ||
   1415 	    (! xdr_int(xdrs, &rec->error)) ||
   1416 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1417 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1418 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1419 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1420 	    (! xdr_int(xdrs, &rec->size)))
   1421 		return (FALSE);
   1422 
   1423 	return (TRUE);
   1424 }
   1425 
   1426 void
   1427 cachefs_log_filldir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1428     fid_t *fidp, ino64_t fileno, u_offset_t size)
   1429 {
   1430 	struct cachefs_log_filldir_record *record;
   1431 
   1432 	/* In Solaris 64 - if can't represent time don't bother */
   1433 	RET_IF_TIME_OVERFLOW(cachep, time)
   1434 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1435 	if (record == NULL) {
   1436 		cachefs_log_error(cachep, ENOMEM, 1);
   1437 		return;
   1438 	}
   1439 
   1440 	record->type = CACHEFS_LOG_FILLDIR;
   1441 	record->time = time;
   1442 	record->error = Errno;
   1443 
   1444 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1445 	if (fidp != NULL) {
   1446 		CACHEFS_FID_COPY(fidp, &record->fid);
   1447 	}
   1448 	record->fileno = fileno;
   1449 	record->size = (uint_t)size;
   1450 
   1451 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1452 	    cachefs_xdr_filldir);
   1453 }
   1454 
   1455 static bool_t
   1456 cachefs_xdr_filldir(XDR *xdrs, struct cachefs_log_filldir_record *rec)
   1457 {
   1458 	if ((! xdr_int(xdrs, &rec->type)) ||
   1459 	    (! xdr_int(xdrs, &rec->error)) ||
   1460 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1461 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1462 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1463 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1464 	    (! xdr_u_int(xdrs, (uint_t *)&rec->size)))
   1465 		return (FALSE);
   1466 
   1467 	return (TRUE);
   1468 }
   1469 
   1470 void
   1471 cachefs_log_mdcreate(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1472     fid_t *fidp, ino64_t fileno, uint_t count)
   1473 {
   1474 	struct cachefs_log_mdcreate_record *record;
   1475 
   1476 	/* In Solaris 64 - if can't represent time don't bother */
   1477 	RET_IF_TIME_OVERFLOW(cachep, time)
   1478 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1479 	if (record == NULL) {
   1480 		cachefs_log_error(cachep, ENOMEM, 1);
   1481 		return;
   1482 	}
   1483 
   1484 	record->type = CACHEFS_LOG_MDCREATE;
   1485 	record->time = time;
   1486 	record->error = Errno;
   1487 
   1488 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1489 	if (fidp != NULL) {
   1490 		CACHEFS_FID_COPY(fidp, &record->fid);
   1491 	}
   1492 	record->fileno = fileno;
   1493 	record->count = count;
   1494 
   1495 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1496 	    cachefs_xdr_mdcreate);
   1497 }
   1498 
   1499 static bool_t
   1500 cachefs_xdr_mdcreate(XDR *xdrs, struct cachefs_log_mdcreate_record *rec)
   1501 {
   1502 	if ((! xdr_int(xdrs, &rec->type)) ||
   1503 	    (! xdr_int(xdrs, &rec->error)) ||
   1504 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1505 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1506 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1507 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1508 	    (! xdr_u_int(xdrs, &rec->count)))
   1509 		return (FALSE);
   1510 
   1511 	return (TRUE);
   1512 }
   1513 
   1514 void
   1515 cachefs_log_gpfront(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1516     fid_t *fidp, ino64_t fileno, uid_t uid, u_offset_t offset, uint_t len)
   1517 {
   1518 	struct cachefs_log_gpfront_record *record;
   1519 
   1520 	/* In Solaris 64 - if can't represent time don't bother */
   1521 	RET_IF_TIME_OVERFLOW(cachep, time)
   1522 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1523 	if (record == NULL) {
   1524 		cachefs_log_error(cachep, ENOMEM, 1);
   1525 		return;
   1526 	}
   1527 
   1528 	record->type = CACHEFS_LOG_GPFRONT;
   1529 	record->time = time;
   1530 	record->error = Errno;
   1531 
   1532 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1533 	if (fidp != NULL) {
   1534 		CACHEFS_FID_COPY(fidp, &record->fid);
   1535 	}
   1536 	record->fileno = fileno;
   1537 	record->uid = uid;
   1538 	record->off = offset;
   1539 	record->len = len;
   1540 
   1541 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1542 	    cachefs_xdr_gpfront);
   1543 }
   1544 
   1545 static bool_t
   1546 cachefs_xdr_gpfront(XDR *xdrs, struct cachefs_log_gpfront_record *rec)
   1547 {
   1548 	if ((! xdr_int(xdrs, &rec->type)) ||
   1549 	    (! xdr_int(xdrs, &rec->error)) ||
   1550 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1551 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1552 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1553 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1554 	    (! xdr_u_int(xdrs, &rec->uid)) ||
   1555 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
   1556 	    (! xdr_u_int(xdrs, &rec->len)))
   1557 		return (FALSE);
   1558 
   1559 	return (TRUE);
   1560 }
   1561 
   1562 void
   1563 cachefs_log_rfdir(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1564     fid_t *fidp, ino64_t fileno, uid_t uid)
   1565 {
   1566 	struct cachefs_log_rfdir_record *record;
   1567 
   1568 	/* In Solaris 64 - if can't represent time don't bother */
   1569 	RET_IF_TIME_OVERFLOW(cachep, time)
   1570 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1571 	if (record == NULL) {
   1572 		cachefs_log_error(cachep, ENOMEM, 1);
   1573 		return;
   1574 	}
   1575 
   1576 	record->type = CACHEFS_LOG_RFDIR;
   1577 	record->time = time;
   1578 	record->error = Errno;
   1579 
   1580 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1581 	if (fidp != NULL) {
   1582 		CACHEFS_FID_COPY(fidp, &record->fid);
   1583 	}
   1584 	record->fileno = fileno;
   1585 	record->uid = uid;
   1586 
   1587 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1588 	    cachefs_xdr_rfdir);
   1589 }
   1590 
   1591 static bool_t
   1592 cachefs_xdr_rfdir(XDR *xdrs, struct cachefs_log_rfdir_record *rec)
   1593 {
   1594 	if ((! xdr_int(xdrs, &rec->type)) ||
   1595 	    (! xdr_int(xdrs, &rec->error)) ||
   1596 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1597 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1598 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1599 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1600 	    (! xdr_u_int(xdrs, &rec->uid)))
   1601 		return (FALSE);
   1602 
   1603 	return (TRUE);
   1604 }
   1605 
   1606 void
   1607 cachefs_log_ualloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1608     fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len)
   1609 {
   1610 	struct cachefs_log_ualloc_record *record;
   1611 
   1612 	/* In Solaris 64 - if can't represent time don't bother */
   1613 	RET_IF_TIME_OVERFLOW(cachep, time)
   1614 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1615 	if (record == NULL) {
   1616 		cachefs_log_error(cachep, ENOMEM, 1);
   1617 		return;
   1618 	}
   1619 
   1620 	record->type = CACHEFS_LOG_UALLOC;
   1621 	record->time = time;
   1622 	record->error = Errno;
   1623 
   1624 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1625 	if (fidp != NULL) {
   1626 		CACHEFS_FID_COPY(fidp, &record->fid);
   1627 	}
   1628 	record->fileno = fileno;
   1629 	record->off = off;
   1630 	record->len = (uint_t)len;
   1631 
   1632 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1633 	    cachefs_xdr_ualloc);
   1634 }
   1635 
   1636 static bool_t
   1637 cachefs_xdr_ualloc(XDR *xdrs, struct cachefs_log_ualloc_record *rec)
   1638 {
   1639 	if ((! xdr_int(xdrs, &rec->type)) ||
   1640 	    (! xdr_int(xdrs, &rec->error)) ||
   1641 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1642 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1643 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1644 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1645 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
   1646 	    (! xdr_u_int(xdrs, (uint_t *)&rec->len)))
   1647 		return (FALSE);
   1648 
   1649 	return (TRUE);
   1650 }
   1651 
   1652 void
   1653 cachefs_log_calloc(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1654     fid_t *fidp, ino64_t fileno, u_offset_t off, size_t len)
   1655 {
   1656 	struct cachefs_log_calloc_record *record;
   1657 
   1658 	/* In Solaris 64 - if can't represent time don't bother */
   1659 	RET_IF_TIME_OVERFLOW(cachep, time)
   1660 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1661 	if (record == NULL) {
   1662 		cachefs_log_error(cachep, ENOMEM, 1);
   1663 		return;
   1664 	}
   1665 
   1666 	record->type = CACHEFS_LOG_CALLOC;
   1667 	record->time = time;
   1668 	record->error = Errno;
   1669 
   1670 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1671 	if (fidp != NULL) {
   1672 		CACHEFS_FID_COPY(fidp, &record->fid);
   1673 	}
   1674 	record->fileno = fileno;
   1675 	record->off = off;
   1676 	record->len = (uint_t)len;
   1677 
   1678 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1679 	    cachefs_xdr_calloc);
   1680 }
   1681 
   1682 static bool_t
   1683 cachefs_xdr_calloc(XDR *xdrs, struct cachefs_log_calloc_record *rec)
   1684 {
   1685 	if ((! xdr_int(xdrs, &rec->type)) ||
   1686 	    (! xdr_int(xdrs, &rec->error)) ||
   1687 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1688 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1689 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1690 	    (! xdr_ino64(xdrs, &rec->fileno)) ||
   1691 	    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rec->off)) ||
   1692 	    (! xdr_u_int(xdrs, &rec->len)))
   1693 		return (FALSE);
   1694 
   1695 	return (TRUE);
   1696 }
   1697 
   1698 void
   1699 cachefs_log_nocache(cachefscache_t *cachep, int Errno, struct vfs *vfsp,
   1700     fid_t *fidp, ino64_t fileno)
   1701 {
   1702 	struct cachefs_log_nocache_record *record;
   1703 
   1704 	/* In Solaris 64 - if can't represent time don't bother */
   1705 	RET_IF_TIME_OVERFLOW(cachep, time)
   1706 	record = cachefs_kmem_zalloc(sizeof (*record), KM_NOSLEEP);
   1707 	if (record == NULL) {
   1708 		cachefs_log_error(cachep, ENOMEM, 1);
   1709 		return;
   1710 	}
   1711 
   1712 	record->type = CACHEFS_LOG_NOCACHE;
   1713 	record->time = time;
   1714 	record->error = Errno;
   1715 
   1716 	record->vfsp = (uint64_t)(uintptr_t)vfsp;
   1717 	if (fidp != NULL) {
   1718 		CACHEFS_FID_COPY(fidp, &record->fid);
   1719 	}
   1720 	record->fileno = fileno;
   1721 
   1722 	cachefs_log_enqueue(cachep, record, (int)sizeof (*record),
   1723 	    cachefs_xdr_nocache);
   1724 
   1725 }
   1726 
   1727 static bool_t
   1728 cachefs_xdr_nocache(XDR *xdrs, struct cachefs_log_nocache_record *rec)
   1729 {
   1730 	if ((! xdr_int(xdrs, &rec->type)) ||
   1731 	    (! xdr_int(xdrs, &rec->error)) ||
   1732 	    (! xdr_cfs_time_t(xdrs, &rec->time)) ||
   1733 	    (! xdr_opaque(xdrs, (caddr_t)&rec->vfsp, sizeof (rec->vfsp))) ||
   1734 	    (! xdr_opaque(xdrs, (caddr_t)&rec->fid, sizeof (rec->fid))) ||
   1735 	    (! xdr_ino64(xdrs, &rec->fileno)))
   1736 		return (FALSE);
   1737 
   1738 	return (TRUE);
   1739 }
   1740