xref: /onnv-gate/usr/src/cmd/fs.d/cachefs/common/stats_log.c (revision 633:04519cb7de3b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*633Sgt29601  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Routines for cachefs logging.
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <stdio.h>
340Sstevel@tonic-gate #include <stdlib.h>
350Sstevel@tonic-gate #include <stddef.h>
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <sys/param.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <sys/stat.h>
400Sstevel@tonic-gate #include <fcntl.h>
410Sstevel@tonic-gate #include <unistd.h>
420Sstevel@tonic-gate #include <libintl.h>
430Sstevel@tonic-gate #include <time.h>
440Sstevel@tonic-gate #include <string.h>
450Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
460Sstevel@tonic-gate #include <sys/fs/cachefs_log.h>
470Sstevel@tonic-gate #include <malloc.h>
480Sstevel@tonic-gate #include <limits.h>
490Sstevel@tonic-gate #include "stats.h"
500Sstevel@tonic-gate #include <assert.h>
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /* forward declarations of statics */
530Sstevel@tonic-gate static kstat_t *stats_log_kstat_read(stats_cookie_t *);
540Sstevel@tonic-gate static char *stats_log_fmtfid(cfs_fid_t *);
550Sstevel@tonic-gate static bool_t stats_xdr_loghead(XDR *, struct cachefs_log_logfile_header *);
560Sstevel@tonic-gate static int stats_log_fi_comp(const void *a, const void *b);
570Sstevel@tonic-gate 
580Sstevel@tonic-gate int
stats_log_kernel_setname(stats_cookie_t * st,char * path)590Sstevel@tonic-gate stats_log_kernel_setname(stats_cookie_t *st, char *path)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	int error = 0;
620Sstevel@tonic-gate 	kstat_t *log;
630Sstevel@tonic-gate 	cachefs_log_control_t *lc;
640Sstevel@tonic-gate 	int exists = 0;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	assert(stats_good(st));
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	if ((log = stats_log_kstat_read(st)) == NULL) {
690Sstevel@tonic-gate 		error = stats_errno(st);
700Sstevel@tonic-gate 		goto out;
710Sstevel@tonic-gate 	}
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	lc = (cachefs_log_control_t *)log->ks_data;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	/*
760Sstevel@tonic-gate 	 * the stats_ API allows a NULL or an empty path to turn off
770Sstevel@tonic-gate 	 * logging, but the kstat interface has the string buffered,
780Sstevel@tonic-gate 	 * so we need to make an empty string.
790Sstevel@tonic-gate 	 */
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	if (path == NULL)
820Sstevel@tonic-gate 		path = "";
830Sstevel@tonic-gate 	if ((lc->lc_path[0] == 0) && (path[0] == 0))
840Sstevel@tonic-gate 		goto out;
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	(void) strlcpy(lc->lc_path, path, sizeof (lc->lc_path));
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	if (path[0] != '\0') {
890Sstevel@tonic-gate 		struct stat64 s;
900Sstevel@tonic-gate 		int f;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 		exists = access(path, F_OK);
930Sstevel@tonic-gate 		/* logfile will be <2GB */
940Sstevel@tonic-gate 		f = open(path, O_WRONLY | O_CREAT, 0666);
950Sstevel@tonic-gate 		if (f < 0) {
960Sstevel@tonic-gate 			stats_perror(st, error = SE_FILE,
970Sstevel@tonic-gate 			    gettext("Cannot open/create logfile: %s"),
980Sstevel@tonic-gate 			    strerror(errno));
990Sstevel@tonic-gate 			goto out;
1000Sstevel@tonic-gate 		}
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 		if (fstat64(f, &s) < 0) {
1030Sstevel@tonic-gate 			stats_perror(st, error = SE_FILE,
1040Sstevel@tonic-gate 			    gettext("Cannot stat logfile: %s"),
1050Sstevel@tonic-gate 			    strerror(errno));
1060Sstevel@tonic-gate 			(void) close(f);
1070Sstevel@tonic-gate 			goto out;
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 		/*
1110Sstevel@tonic-gate 		 * the kernel will accept an empty file as a logfile.  we must
1120Sstevel@tonic-gate 		 * make sure that we created this empty file, i.e. that it's
1130Sstevel@tonic-gate 		 * not an already existing file that happened to be empty.
1140Sstevel@tonic-gate 		 *
1150Sstevel@tonic-gate 		 * if we hand the kernel a nonempty file, it will check the
1160Sstevel@tonic-gate 		 * magic number.  thus, if they hand it something like
1170Sstevel@tonic-gate 		 * /etc/passwd, the kernel should reject it.  we just have to
1180Sstevel@tonic-gate 		 * catch the cases of empty files we don't want to be
1190Sstevel@tonic-gate 		 * logfiles.
1200Sstevel@tonic-gate 		 */
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 		if ((exists == 0) && (s.st_size == 0LL)) {
1230Sstevel@tonic-gate 			stats_perror(st, error = SE_INVAL,
1240Sstevel@tonic-gate 			    gettext(
1250Sstevel@tonic-gate 			    "Cannot use existing empty file as a logfile"));
1260Sstevel@tonic-gate 			(void) close(f);
1270Sstevel@tonic-gate 			goto out;
1280Sstevel@tonic-gate 		}
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 		(void) close(f);
1310Sstevel@tonic-gate 	}
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (kstat_write(st->st_kstat_cookie, log, NULL) < 0) {
1340Sstevel@tonic-gate 		stats_perror(st, error = SE_KERNEL,
1350Sstevel@tonic-gate 		    gettext("Cannot set logfile path for this filesystem"));
1360Sstevel@tonic-gate 		goto out;
1370Sstevel@tonic-gate 	}
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate out:
1400Sstevel@tonic-gate 	if ((error != 0) && (path[0] != '\0') && (exists != 0))
1410Sstevel@tonic-gate 		(void) unlink(path);
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	return (error);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate int
stats_log_which(stats_cookie_t * st,int which,int onoff)1470Sstevel@tonic-gate stats_log_which(stats_cookie_t *st, int which, int onoff)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate 	int error = 0;
1500Sstevel@tonic-gate 	kstat_t *log;
1510Sstevel@tonic-gate 	cachefs_log_control_t *lc;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	assert(stats_good(st));
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	if ((log = stats_log_kstat_read(st)) == NULL) {
1560Sstevel@tonic-gate 		error = stats_errno(st);
1570Sstevel@tonic-gate 		goto out;
1580Sstevel@tonic-gate 	}
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	lc = (cachefs_log_control_t *)log->ks_data;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	if (onoff)
1630Sstevel@tonic-gate 		CACHEFS_LOG_SET(lc, which);
1640Sstevel@tonic-gate 	else
1650Sstevel@tonic-gate 		CACHEFS_LOG_CLEAR(lc, which);
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	if (kstat_write(st->st_kstat_cookie, log, NULL) < 0) {
1680Sstevel@tonic-gate 		stats_perror(st, error = SE_KERNEL,
1690Sstevel@tonic-gate 		    gettext("Cannot set log bitmap for this filesystem"));
1700Sstevel@tonic-gate 		goto out;
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate out:
1740Sstevel@tonic-gate 	return (error);
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate char *
stats_log_kernel_getname(stats_cookie_t * st)1780Sstevel@tonic-gate stats_log_kernel_getname(stats_cookie_t *st)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate 	char *rc = NULL;
1810Sstevel@tonic-gate 	kstat_t *log;
1820Sstevel@tonic-gate 	cachefs_log_control_t *lc;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	assert(stats_good(st));
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	if ((log = stats_log_kstat_read(st)) == NULL)
1870Sstevel@tonic-gate 		goto out;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	lc = (cachefs_log_control_t *)log->ks_data;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	rc = lc->lc_path; /* rc[0] will be '\0' if we're not logging */
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate out:
1940Sstevel@tonic-gate 	return (rc);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate static kstat_t *
stats_log_kstat_read(stats_cookie_t * st)1980Sstevel@tonic-gate stats_log_kstat_read(stats_cookie_t *st)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate 	kstat_t *rc;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	assert(stats_good(st));
2030Sstevel@tonic-gate 	assert(st->st_flags & ST_BOUND);
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if ((rc = kstat_lookup(st->st_kstat_cookie,
2060Sstevel@tonic-gate 	    "cachefs", st->st_fsid, "log")) == NULL) {
2070Sstevel@tonic-gate 		/*
2080Sstevel@tonic-gate 		 * XXX if st was created for a particular cachedir, we
2090Sstevel@tonic-gate 		 * should scan for another st->st_fsid that'll get us
2100Sstevel@tonic-gate 		 * the same cache.
2110Sstevel@tonic-gate 		 */
2120Sstevel@tonic-gate 		stats_perror(st, SE_KERNEL,
2130Sstevel@tonic-gate 		    gettext("Cannot lookup kstats for this filesystem"));
2140Sstevel@tonic-gate 		goto out;
2150Sstevel@tonic-gate 	}
2160Sstevel@tonic-gate 	if (kstat_read(st->st_kstat_cookie, rc, NULL) < 0) {
2170Sstevel@tonic-gate 		stats_perror(st, SE_KERNEL,
2180Sstevel@tonic-gate 		    gettext("Cannot read kstats for this filesystem"));
2190Sstevel@tonic-gate 		rc = NULL;
2200Sstevel@tonic-gate 		goto out;
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate out:
2240Sstevel@tonic-gate 	return (rc);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate int
stats_log_logfile_open(stats_cookie_t * st,char * fname)2280Sstevel@tonic-gate stats_log_logfile_open(stats_cookie_t *st, char *fname)
2290Sstevel@tonic-gate {
2300Sstevel@tonic-gate 	int rc = 0;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	assert(stats_good(st));
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if ((fname == NULL) || (fname[0] == '\0')) {
2350Sstevel@tonic-gate 		kstat_t *log;
2360Sstevel@tonic-gate 		cachefs_log_control_t *lc;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 		if ((log = stats_log_kstat_read(st)) == NULL) {
2390Sstevel@tonic-gate 			rc = -1;
2400Sstevel@tonic-gate 			goto out;
2410Sstevel@tonic-gate 		}
2420Sstevel@tonic-gate 		lc = (cachefs_log_control_t *)log->ks_data;
2430Sstevel@tonic-gate 		fname = lc->lc_path;
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	/* logfile will be <2GB */
2470Sstevel@tonic-gate 	if ((st->st_logstream = fopen(fname, "r")) == NULL) {
2480Sstevel@tonic-gate 		stats_perror(st, SE_FILE,
2490Sstevel@tonic-gate 		    gettext("Cannot open logfile %s"), fname);
2500Sstevel@tonic-gate 		rc = -1;
2510Sstevel@tonic-gate 		goto out;
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 	xdrstdio_create(&st->st_logxdr, st->st_logstream, XDR_DECODE);
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	if (! stats_xdr_loghead(&st->st_logxdr, &st->st_loghead)) {
2560Sstevel@tonic-gate 		stats_perror(st, SE_CORRUPT,
2570Sstevel@tonic-gate 		    gettext("Cannot read header from logfile %s"), fname);
2580Sstevel@tonic-gate 		rc = -1;
2590Sstevel@tonic-gate 		goto out;
2600Sstevel@tonic-gate 	}
2610Sstevel@tonic-gate 	if (st->st_loghead.lh_magic != CACHEFS_LOG_MAGIC) {
2620Sstevel@tonic-gate 		stats_perror(st, SE_CORRUPT,
2630Sstevel@tonic-gate 		    gettext("%s: Invalid log file header"), fname);
2640Sstevel@tonic-gate 		rc = -1;
2650Sstevel@tonic-gate 		goto out;
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 	if (st->st_loghead.lh_revision > CACHEFS_LOG_FILE_REV) {
2680Sstevel@tonic-gate 		stats_perror(st, SE_CORRUPT,
2690Sstevel@tonic-gate 		    gettext("%s: Revision too high"), fname);
2700Sstevel@tonic-gate 		rc = -1;
2710Sstevel@tonic-gate 		goto out;
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	st->st_flags |= ST_LFOPEN;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate out:
2770Sstevel@tonic-gate 	if (rc != 0) {
2780Sstevel@tonic-gate 		if (st->st_logstream != NULL) {
2790Sstevel@tonic-gate 			(void) fclose(st->st_logstream);
2800Sstevel@tonic-gate 			st->st_logstream = NULL;
2810Sstevel@tonic-gate 		}
2820Sstevel@tonic-gate 		if (st->st_logxdr.x_ops != NULL) {
2830Sstevel@tonic-gate 			xdr_destroy(&st->st_logxdr);
2840Sstevel@tonic-gate 			st->st_logxdr.x_ops = NULL;
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 	}
2870Sstevel@tonic-gate 	return (rc);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate static bool_t
stats_xdr_loghead(XDR * xdrs,struct cachefs_log_logfile_header * lh)2910Sstevel@tonic-gate stats_xdr_loghead(XDR *xdrs, struct cachefs_log_logfile_header *lh)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate 	if ((! xdr_u_int(xdrs, &lh->lh_magic)) ||
2940Sstevel@tonic-gate 	    (! xdr_u_int(xdrs, &lh->lh_revision)) ||
2950Sstevel@tonic-gate 	    (! xdr_int(xdrs, &lh->lh_errno)) ||
2960Sstevel@tonic-gate 	    (! xdr_u_int(xdrs, &lh->lh_blocks)) ||
2970Sstevel@tonic-gate 	    (! xdr_u_int(xdrs, &lh->lh_files)) ||
2980Sstevel@tonic-gate 	    (! xdr_u_int(xdrs, &lh->lh_maxbsize)) ||
2990Sstevel@tonic-gate 	    (! xdr_u_int(xdrs, &lh->lh_pagesize)))
3000Sstevel@tonic-gate 		return (FALSE);
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	return (TRUE);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate void *
stats_log_logfile_read(stats_cookie_t * st,int * type)3060Sstevel@tonic-gate stats_log_logfile_read(stats_cookie_t *st, int *type)
3070Sstevel@tonic-gate {
3080Sstevel@tonic-gate 	void *rc = NULL;
3090Sstevel@tonic-gate 	size_t size;
3100Sstevel@tonic-gate 	int ttype;
3110Sstevel@tonic-gate 	XDR *xdrs;
3120Sstevel@tonic-gate 	char *string1, *string2;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	assert(stats_good(st));
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	xdrs = &st->st_logxdr;
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	if (! (st->st_flags & ST_LFOPEN)) {
3190Sstevel@tonic-gate 		stats_perror(st, SE_INVAL,
3200Sstevel@tonic-gate 		    gettext("Logfile was not open"));
3210Sstevel@tonic-gate 		goto out;
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	if (type == NULL)
3250Sstevel@tonic-gate 		type = &ttype;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	if (! xdr_int(xdrs, type))
3280Sstevel@tonic-gate 		goto out;
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	switch (*type) {
3310Sstevel@tonic-gate 		struct cachefs_log_mount_record mount, *mountp;
3320Sstevel@tonic-gate 		struct cachefs_log_umount_record umount;
3330Sstevel@tonic-gate 		struct cachefs_log_getpage_record getpage;
3340Sstevel@tonic-gate 		struct cachefs_log_readdir_record readdir;
3350Sstevel@tonic-gate 		struct cachefs_log_readlink_record readlink;
3360Sstevel@tonic-gate 		struct cachefs_log_remove_record remove;
3370Sstevel@tonic-gate 		struct cachefs_log_rmdir_record rmdir;
3380Sstevel@tonic-gate 		struct cachefs_log_truncate_record truncate;
3390Sstevel@tonic-gate 		struct cachefs_log_putpage_record putpage;
3400Sstevel@tonic-gate 		struct cachefs_log_create_record create;
3410Sstevel@tonic-gate 		struct cachefs_log_mkdir_record mkdir;
3420Sstevel@tonic-gate 		struct cachefs_log_rename_record rename;
3430Sstevel@tonic-gate 		struct cachefs_log_symlink_record symlink;
3440Sstevel@tonic-gate 		struct cachefs_log_populate_record populate;
3450Sstevel@tonic-gate 		struct cachefs_log_csymlink_record csymlink;
3460Sstevel@tonic-gate 		struct cachefs_log_filldir_record filldir;
3470Sstevel@tonic-gate 		struct cachefs_log_mdcreate_record mdcreate;
3480Sstevel@tonic-gate 		struct cachefs_log_gpfront_record gpfront;
3490Sstevel@tonic-gate 		struct cachefs_log_rfdir_record rfdir;
3500Sstevel@tonic-gate 		struct cachefs_log_ualloc_record ualloc;
3510Sstevel@tonic-gate 		struct cachefs_log_calloc_record challoc;
3520Sstevel@tonic-gate 		struct cachefs_log_nocache_record nocache;
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	case CACHEFS_LOG_MOUNT:
3550Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &mount.error)) ||
3560Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&mount.time)) ||
3570Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&mount.vfsp,
3580Sstevel@tonic-gate 		    sizeof (mount.vfsp))) ||
3590Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &mount.flags)) ||
3600Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &mount.popsize)) ||
3610Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &mount.fgsize)) ||
3620Sstevel@tonic-gate 		    (! xdr_u_short(xdrs, &mount.pathlen)) ||
3630Sstevel@tonic-gate 		    (! xdr_u_short(xdrs, &mount.cacheidlen))) {
3640Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
3650Sstevel@tonic-gate 			    gettext("Truncated mount record"));
3660Sstevel@tonic-gate 			goto out;
3670Sstevel@tonic-gate 		}
3680Sstevel@tonic-gate 		mount.type = *type;
3690Sstevel@tonic-gate 		size = sizeof (mount) + mount.pathlen + mount.cacheidlen -
3700Sstevel@tonic-gate 			CLPAD(cachefs_log_mount_record, path);
3710Sstevel@tonic-gate 		if ((rc = mountp =
3720Sstevel@tonic-gate 		    (struct cachefs_log_mount_record *)
3730Sstevel@tonic-gate 		    calloc(1, size)) == NULL) {
3740Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
3750Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
3760Sstevel@tonic-gate 			goto out;
3770Sstevel@tonic-gate 		}
3780Sstevel@tonic-gate 		memcpy(rc, &mount, size);
3790Sstevel@tonic-gate 		string1 = mountp->path;
3800Sstevel@tonic-gate 		string2 = mountp->path + mount.pathlen + 1;
3810Sstevel@tonic-gate 		(void) xdr_wrapstring(xdrs, &string1);
3820Sstevel@tonic-gate 		(void) xdr_wrapstring(xdrs, &string2);
3830Sstevel@tonic-gate 		break;
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	case CACHEFS_LOG_UMOUNT:
3860Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &umount.error)) ||
3870Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&umount.time)) ||
3880Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&umount.vfsp,
3890Sstevel@tonic-gate 		    sizeof (umount.vfsp)))) {
3900Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
3910Sstevel@tonic-gate 			    gettext("Truncated umount record"));
3920Sstevel@tonic-gate 			goto out;
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 		umount.type = *type;
3950Sstevel@tonic-gate 		size = sizeof (umount);
3960Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
3970Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
3980Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
3990Sstevel@tonic-gate 			goto out;
4000Sstevel@tonic-gate 		}
4010Sstevel@tonic-gate 		memcpy(rc, &umount, size);
4020Sstevel@tonic-gate 		break;
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	case CACHEFS_LOG_GETPAGE:
4050Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &getpage.error)) ||
4060Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&getpage.time)) ||
4070Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&getpage.vfsp,
4080Sstevel@tonic-gate 		    sizeof (getpage.vfsp))) ||
4090Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&getpage.fid,
4100Sstevel@tonic-gate 		    sizeof (getpage.fid))) ||
4110Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
4120Sstevel@tonic-gate 		    (u_longlong_t *)&getpage.fileno)) ||
4130Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&getpage.uid)) ||
4140Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
4150Sstevel@tonic-gate 		    (u_longlong_t *)&getpage.offset)) ||
4160Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &getpage.len))) {
4170Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
4180Sstevel@tonic-gate 			    gettext("Truncated getpage record"));
4190Sstevel@tonic-gate 			goto out;
4200Sstevel@tonic-gate 		}
4210Sstevel@tonic-gate 		getpage.type = *type;
4220Sstevel@tonic-gate 		size = sizeof (getpage);
4230Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
4240Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
4250Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
4260Sstevel@tonic-gate 			goto out;
4270Sstevel@tonic-gate 		}
4280Sstevel@tonic-gate 		memcpy(rc, &getpage, size);
4290Sstevel@tonic-gate 		break;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	case CACHEFS_LOG_READDIR:
4320Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &readdir.error)) ||
4330Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&readdir.time)) ||
4340Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&readdir.vfsp,
4350Sstevel@tonic-gate 		    sizeof (readdir.vfsp))) ||
4360Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&readdir.fid,
4370Sstevel@tonic-gate 		    sizeof (readdir.fid))) ||
4380Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
4390Sstevel@tonic-gate 		    (u_longlong_t *)&readdir.fileno)) ||
4400Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&readdir.uid)) ||
4410Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
4420Sstevel@tonic-gate 		    (u_longlong_t *)&readdir.offset)) ||
4430Sstevel@tonic-gate 		    (! xdr_int(xdrs, &readdir.eof))) {
4440Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
4450Sstevel@tonic-gate 			    gettext("Truncated readdir record"));
4460Sstevel@tonic-gate 			goto out;
4470Sstevel@tonic-gate 		}
4480Sstevel@tonic-gate 		readdir.type = *type;
4490Sstevel@tonic-gate 		size = sizeof (readdir);
4500Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
4510Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
4520Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
4530Sstevel@tonic-gate 			goto out;
4540Sstevel@tonic-gate 		}
4550Sstevel@tonic-gate 		memcpy(rc, &readdir, size);
4560Sstevel@tonic-gate 		break;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	case CACHEFS_LOG_READLINK:
4590Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &readlink.error)) ||
4600Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&readlink.time)) ||
4610Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&readlink.vfsp,
4620Sstevel@tonic-gate 		    sizeof (readlink.vfsp))) ||
4630Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&readlink.fid,
4640Sstevel@tonic-gate 		    sizeof (readlink.fid))) ||
4650Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
4660Sstevel@tonic-gate 		    (u_longlong_t *)&readlink.fileno)) ||
4670Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&readlink.uid)) ||
4680Sstevel@tonic-gate 		    (! xdr_u_int(xdrs,
4690Sstevel@tonic-gate 		    &readlink.length))) {
4700Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
4710Sstevel@tonic-gate 			    gettext("Truncated readlink record"));
4720Sstevel@tonic-gate 			goto out;
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate 		readlink.type = *type;
4750Sstevel@tonic-gate 		size = sizeof (readlink);
4760Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
4770Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
4780Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
4790Sstevel@tonic-gate 			goto out;
4800Sstevel@tonic-gate 		}
4810Sstevel@tonic-gate 		memcpy(rc, &readlink, size);
4820Sstevel@tonic-gate 		break;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	case CACHEFS_LOG_REMOVE:
4850Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &remove.error)) ||
4860Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&remove.time)) ||
4870Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&remove.vfsp,
4880Sstevel@tonic-gate 		    sizeof (remove.vfsp))) ||
4890Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&remove.fid,
4900Sstevel@tonic-gate 		    sizeof (remove.fid))) ||
4910Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
4920Sstevel@tonic-gate 		    (u_longlong_t *)&remove.fileno)) ||
4930Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&remove.uid))) {
4940Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
4950Sstevel@tonic-gate 			    gettext("Truncated remove record"));
4960Sstevel@tonic-gate 			goto out;
4970Sstevel@tonic-gate 		}
4980Sstevel@tonic-gate 		remove.type = *type;
4990Sstevel@tonic-gate 		size = sizeof (remove);
5000Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
5010Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
5020Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
5030Sstevel@tonic-gate 			goto out;
5040Sstevel@tonic-gate 		}
5050Sstevel@tonic-gate 		memcpy(rc, &remove, size);
5060Sstevel@tonic-gate 		break;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	case CACHEFS_LOG_RMDIR:
5090Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &rmdir.error)) ||
5100Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&rmdir.time)) ||
5110Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&rmdir.vfsp,
5120Sstevel@tonic-gate 		    sizeof (rmdir.vfsp))) ||
5130Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&rmdir.fid,
5140Sstevel@tonic-gate 		    sizeof (rmdir.fid))) ||
5150Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rmdir.fileno)) ||
5160Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&rmdir.uid))) {
5170Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
5180Sstevel@tonic-gate 			    gettext("Truncated rmdir record"));
5190Sstevel@tonic-gate 			goto out;
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 		rmdir.type = *type;
5220Sstevel@tonic-gate 		size = sizeof (rmdir);
5230Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
5240Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
5250Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
5260Sstevel@tonic-gate 			goto out;
5270Sstevel@tonic-gate 		}
5280Sstevel@tonic-gate 		memcpy(rc, &rmdir, size);
5290Sstevel@tonic-gate 		break;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	case CACHEFS_LOG_TRUNCATE:
5320Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &truncate.error)) ||
5330Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&truncate.time)) ||
5340Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&truncate.vfsp,
5350Sstevel@tonic-gate 		    sizeof (truncate.vfsp))) ||
5360Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&truncate.fid,
5370Sstevel@tonic-gate 		    sizeof (truncate.fid))) ||
5380Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
5390Sstevel@tonic-gate 		    (u_longlong_t *)&truncate.fileno)) ||
5400Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&truncate.uid)) ||
5410Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
5420Sstevel@tonic-gate 		    (u_longlong_t *)&truncate.size))) {
5430Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
5440Sstevel@tonic-gate 			    gettext("Truncated truncate record"));
5450Sstevel@tonic-gate 			goto out;
5460Sstevel@tonic-gate 		}
5470Sstevel@tonic-gate 		truncate.type = *type;
5480Sstevel@tonic-gate 		size = sizeof (truncate);
5490Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
5500Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
5510Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
5520Sstevel@tonic-gate 			goto out;
5530Sstevel@tonic-gate 		}
5540Sstevel@tonic-gate 		memcpy(rc, &truncate, size);
5550Sstevel@tonic-gate 		break;
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	case CACHEFS_LOG_PUTPAGE:
5580Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &putpage.error)) ||
5590Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&putpage.time)) ||
5600Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&putpage.vfsp,
5610Sstevel@tonic-gate 		    sizeof (putpage.vfsp))) ||
5620Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&putpage.fid,
5630Sstevel@tonic-gate 		    sizeof (putpage.fid))) ||
5640Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
5650Sstevel@tonic-gate 		    (u_longlong_t *)&putpage.fileno)) ||
5660Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&putpage.uid)) ||
5670Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
5680Sstevel@tonic-gate 		    (u_longlong_t *)&putpage.offset)) ||
5690Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &putpage.len))) {
5700Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
5710Sstevel@tonic-gate 			    gettext("Truncated putpage record"));
5720Sstevel@tonic-gate 			goto out;
5730Sstevel@tonic-gate 		}
5740Sstevel@tonic-gate 		putpage.type = *type;
5750Sstevel@tonic-gate 		size = sizeof (putpage);
5760Sstevel@tonic-gate 		if ((rc = (caddr_t)calloc(1, size)) == NULL) {
5770Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
5780Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
5790Sstevel@tonic-gate 			goto out;
5800Sstevel@tonic-gate 		}
5810Sstevel@tonic-gate 		memcpy(rc, &putpage, size);
5820Sstevel@tonic-gate 		break;
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	case CACHEFS_LOG_CREATE:
5850Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &create.error)) ||
5860Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&create.time)) ||
5870Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&create.vfsp,
5880Sstevel@tonic-gate 		    sizeof (create.vfsp))) ||
5890Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&create.fid,
5900Sstevel@tonic-gate 		    sizeof (create.fid))) ||
5910Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
5920Sstevel@tonic-gate 		    (u_longlong_t *)&create.fileno)) ||
5930Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&create.uid))) {
5940Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
5950Sstevel@tonic-gate 			    gettext("Truncated create record"));
5960Sstevel@tonic-gate 			goto out;
5970Sstevel@tonic-gate 		}
5980Sstevel@tonic-gate 		create.type = *type;
5990Sstevel@tonic-gate 		size = sizeof (create);
6000Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_create_record *)
6010Sstevel@tonic-gate 		    calloc(1, size)) == NULL) {
6020Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
6030Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
6040Sstevel@tonic-gate 			goto out;
6050Sstevel@tonic-gate 		}
6060Sstevel@tonic-gate 		memcpy(rc, &create, size);
6070Sstevel@tonic-gate 		break;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	case CACHEFS_LOG_MKDIR:
6100Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &mkdir.error)) ||
6110Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&mkdir.time)) ||
6120Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&mkdir.vfsp,
6130Sstevel@tonic-gate 		    sizeof (mkdir.vfsp))) ||
6140Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&mkdir.fid,
6150Sstevel@tonic-gate 		    sizeof (mkdir.fid))) ||
6160Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&mkdir.fileno)) ||
6170Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&mkdir.uid))) {
6180Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
6190Sstevel@tonic-gate 			    gettext("Truncated mkdir record"));
6200Sstevel@tonic-gate 			goto out;
6210Sstevel@tonic-gate 		}
6220Sstevel@tonic-gate 		mkdir.type = *type;
6230Sstevel@tonic-gate 		size = sizeof (mkdir);
6240Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_mkdir_record *)
6250Sstevel@tonic-gate 		    calloc(1, size)) == NULL) {
6260Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
6270Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
6280Sstevel@tonic-gate 			goto out;
6290Sstevel@tonic-gate 		}
6300Sstevel@tonic-gate 		memcpy(rc, &mkdir, size);
6310Sstevel@tonic-gate 		break;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	case CACHEFS_LOG_RENAME:
6340Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &rename.error)) ||
6350Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&rename.time)) ||
6360Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&rename.vfsp,
6370Sstevel@tonic-gate 		    sizeof (rename.vfsp))) ||
6380Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&rename.gone,
6390Sstevel@tonic-gate 		    sizeof (rename.gone))) ||
6400Sstevel@tonic-gate 		    (! xdr_int(xdrs, &rename.removed)) ||
6410Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&rename.uid))) {
6420Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
6430Sstevel@tonic-gate 			    gettext("Truncated rename record"));
6440Sstevel@tonic-gate 			goto out;
6450Sstevel@tonic-gate 		}
6460Sstevel@tonic-gate 		rename.type = *type;
6470Sstevel@tonic-gate 		size = sizeof (rename);
6480Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_rename_record *)
6490Sstevel@tonic-gate 		    calloc(1, size)) == NULL) {
6500Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
6510Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
6520Sstevel@tonic-gate 			goto out;
6530Sstevel@tonic-gate 		}
6540Sstevel@tonic-gate 		memcpy(rc, &rename, size);
6550Sstevel@tonic-gate 		break;
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	case CACHEFS_LOG_SYMLINK:
6580Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &symlink.error)) ||
6590Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&symlink.time)) ||
6600Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&symlink.vfsp,
6610Sstevel@tonic-gate 		    sizeof (symlink.vfsp))) ||
6620Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&symlink.fid,
6630Sstevel@tonic-gate 		    sizeof (symlink.fid))) ||
6640Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
6650Sstevel@tonic-gate 		    (u_longlong_t *)&symlink.fileno)) ||
6660Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&symlink.uid)) ||
6670Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &symlink.size))) {
6680Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
6690Sstevel@tonic-gate 			    gettext("Truncated symlink record"));
6700Sstevel@tonic-gate 			goto out;
6710Sstevel@tonic-gate 		}
6720Sstevel@tonic-gate 		symlink.type = *type;
6730Sstevel@tonic-gate 		size = sizeof (symlink);
6740Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_symlink_record *)
6750Sstevel@tonic-gate 		    calloc(1, size)) == NULL) {
6760Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
6770Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
6780Sstevel@tonic-gate 			goto out;
6790Sstevel@tonic-gate 		}
6800Sstevel@tonic-gate 		memcpy(rc, &symlink, size);
6810Sstevel@tonic-gate 		break;
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	case CACHEFS_LOG_POPULATE:
6840Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &populate.error)) ||
6850Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&populate.time)) ||
6860Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&populate.vfsp,
6870Sstevel@tonic-gate 		    sizeof (populate.vfsp))) ||
6880Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&populate.fid,
6890Sstevel@tonic-gate 		    sizeof (populate.fid))) ||
6900Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
6910Sstevel@tonic-gate 		    (u_longlong_t *)&populate.fileno)) ||
6920Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&populate.off)) ||
6930Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &populate.size))) {
6940Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
6950Sstevel@tonic-gate 			    gettext("Truncated populate record"));
6960Sstevel@tonic-gate 			goto out;
6970Sstevel@tonic-gate 		}
6980Sstevel@tonic-gate 		populate.type = *type;
6990Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_populate_record *)
7000Sstevel@tonic-gate 		    calloc(1, sizeof (populate))) == NULL) {
7010Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
7020Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
7030Sstevel@tonic-gate 			goto out;
7040Sstevel@tonic-gate 		}
7050Sstevel@tonic-gate 		memcpy(rc, &populate, sizeof (populate));
7060Sstevel@tonic-gate 		break;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	case CACHEFS_LOG_CSYMLINK:
7090Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &csymlink.error)) ||
7100Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&csymlink.time)) ||
7110Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&csymlink.vfsp,
7120Sstevel@tonic-gate 		    sizeof (csymlink.vfsp))) ||
7130Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&csymlink.fid,
7140Sstevel@tonic-gate 		    sizeof (csymlink.fid))) ||
7150Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
7160Sstevel@tonic-gate 		    (u_longlong_t *)&csymlink.fileno)) ||
7170Sstevel@tonic-gate 		    (! xdr_int(xdrs, &csymlink.size))) {
7180Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
7190Sstevel@tonic-gate 			    gettext("Truncated csymlink record"));
7200Sstevel@tonic-gate 			goto out;
7210Sstevel@tonic-gate 		}
7220Sstevel@tonic-gate 		csymlink.type = *type;
7230Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_csymlink_record *)
7240Sstevel@tonic-gate 		    calloc(1, sizeof (csymlink))) == NULL) {
7250Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
7260Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
7270Sstevel@tonic-gate 			goto out;
7280Sstevel@tonic-gate 		}
7290Sstevel@tonic-gate 		memcpy(rc, &csymlink, sizeof (csymlink));
7300Sstevel@tonic-gate 		break;
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	case CACHEFS_LOG_FILLDIR:
7330Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &filldir.error)) ||
7340Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&filldir.time)) ||
7350Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&filldir.vfsp,
7360Sstevel@tonic-gate 		    sizeof (filldir.vfsp))) ||
7370Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&filldir.fid,
7380Sstevel@tonic-gate 		    sizeof (filldir.fid))) ||
7390Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
7400Sstevel@tonic-gate 		    (u_longlong_t *)&filldir.fileno)) ||
7410Sstevel@tonic-gate 		    (! xdr_int(xdrs, &filldir.size))) {
7420Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
7430Sstevel@tonic-gate 			    gettext("Truncated filldir record"));
7440Sstevel@tonic-gate 			goto out;
7450Sstevel@tonic-gate 		}
7460Sstevel@tonic-gate 		filldir.type = *type;
7470Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_filldir_record *)
7480Sstevel@tonic-gate 		    calloc(1, sizeof (filldir))) == NULL) {
7490Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
7500Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
7510Sstevel@tonic-gate 			goto out;
7520Sstevel@tonic-gate 		}
7530Sstevel@tonic-gate 		memcpy(rc, &filldir, sizeof (filldir));
7540Sstevel@tonic-gate 		break;
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	case CACHEFS_LOG_MDCREATE:
7570Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &mdcreate.error)) ||
7580Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&mdcreate.time)) ||
7590Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&mdcreate.vfsp,
7600Sstevel@tonic-gate 		    sizeof (mdcreate.vfsp))) ||
7610Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&mdcreate.fid,
7620Sstevel@tonic-gate 		    sizeof (mdcreate.fid))) ||
7630Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
7640Sstevel@tonic-gate 		    (u_longlong_t *)&mdcreate.fileno)) ||
7650Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &mdcreate.count))) {
7660Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
7670Sstevel@tonic-gate 			    gettext("Truncated mdcreate record"));
7680Sstevel@tonic-gate 			goto out;
7690Sstevel@tonic-gate 		}
7700Sstevel@tonic-gate 		mdcreate.type = *type;
7710Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_mdcreate_record *)
7720Sstevel@tonic-gate 		    calloc(1, sizeof (mdcreate))) == NULL) {
7730Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
7740Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
7750Sstevel@tonic-gate 			goto out;
7760Sstevel@tonic-gate 		}
7770Sstevel@tonic-gate 		memcpy(rc, &mdcreate, sizeof (mdcreate));
7780Sstevel@tonic-gate 		break;
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	case CACHEFS_LOG_GPFRONT:
7810Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &gpfront.error)) ||
7820Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&gpfront.time)) ||
7830Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&gpfront.vfsp,
7840Sstevel@tonic-gate 		    sizeof (gpfront.vfsp))) ||
7850Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&gpfront.fid,
7860Sstevel@tonic-gate 		    sizeof (gpfront.fid))) ||
7870Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
7880Sstevel@tonic-gate 		    (u_longlong_t *)&gpfront.fileno)) ||
7890Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&gpfront.uid)) ||
7900Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&gpfront.off)) ||
7910Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &gpfront.len))) {
7920Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
7930Sstevel@tonic-gate 			    gettext("Truncated gpfront record"));
7940Sstevel@tonic-gate 			goto out;
7950Sstevel@tonic-gate 		}
7960Sstevel@tonic-gate 		gpfront.type = *type;
7970Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_gpfront_record *)
7980Sstevel@tonic-gate 		    calloc(1, sizeof (gpfront))) == NULL) {
7990Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
8000Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
8010Sstevel@tonic-gate 			goto out;
8020Sstevel@tonic-gate 		}
8030Sstevel@tonic-gate 		memcpy(rc, &gpfront, sizeof (gpfront));
8040Sstevel@tonic-gate 		break;
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	case CACHEFS_LOG_RFDIR:
8070Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &rfdir.error)) ||
8080Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&rfdir.time)) ||
8090Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&rfdir.vfsp,
8100Sstevel@tonic-gate 		    sizeof (rfdir.vfsp))) ||
8110Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&rfdir.fid,
8120Sstevel@tonic-gate 		    sizeof (rfdir.fid))) ||
8130Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&rfdir.fileno)) ||
8140Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&rfdir.uid))) {
8150Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
8160Sstevel@tonic-gate 			    gettext("Truncated rfdir record"));
8170Sstevel@tonic-gate 			goto out;
8180Sstevel@tonic-gate 		}
8190Sstevel@tonic-gate 		rfdir.type = *type;
8200Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_rfdir_record *)
8210Sstevel@tonic-gate 		    calloc(1, sizeof (rfdir))) == NULL) {
8220Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
8230Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
8240Sstevel@tonic-gate 			goto out;
8250Sstevel@tonic-gate 		}
8260Sstevel@tonic-gate 		memcpy(rc, &rfdir, sizeof (rfdir));
8270Sstevel@tonic-gate 		break;
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	case CACHEFS_LOG_UALLOC:
8300Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &ualloc.error)) ||
8310Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&ualloc.time)) ||
8320Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&ualloc.vfsp,
8330Sstevel@tonic-gate 		    sizeof (ualloc.vfsp))) ||
8340Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&ualloc.fid,
8350Sstevel@tonic-gate 		    sizeof (ualloc.fid))) ||
8360Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
8370Sstevel@tonic-gate 		    (u_longlong_t *)&ualloc.fileno)) ||
8380Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&ualloc.off)) ||
8390Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &ualloc.len))) {
8400Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
8410Sstevel@tonic-gate 			    gettext("Truncated ualloc record"));
8420Sstevel@tonic-gate 			goto out;
8430Sstevel@tonic-gate 		}
8440Sstevel@tonic-gate 		ualloc.type = *type;
8450Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_ualloc_record *)
8460Sstevel@tonic-gate 		    calloc(1, sizeof (ualloc))) == NULL) {
8470Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
8480Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
8490Sstevel@tonic-gate 			goto out;
8500Sstevel@tonic-gate 		}
8510Sstevel@tonic-gate 		memcpy(rc, &ualloc, sizeof (ualloc));
8520Sstevel@tonic-gate 		break;
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	case CACHEFS_LOG_CALLOC:
8550Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &challoc.error)) ||
8560Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&challoc.time)) ||
8570Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&challoc.vfsp,
8580Sstevel@tonic-gate 		    sizeof (challoc.vfsp))) ||
8590Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&challoc.fid,
8600Sstevel@tonic-gate 		    sizeof (challoc.fid))) ||
8610Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
8620Sstevel@tonic-gate 		    (u_longlong_t *)&challoc.fileno)) ||
8630Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs, (u_longlong_t *)&challoc.off)) ||
8640Sstevel@tonic-gate 		    (! xdr_u_int(xdrs, &challoc.len))) {
8650Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
8660Sstevel@tonic-gate 			    gettext("Truncated calloc record"));
8670Sstevel@tonic-gate 			goto out;
8680Sstevel@tonic-gate 		}
8690Sstevel@tonic-gate 		challoc.type = *type;
8700Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_calloc_record *)
8710Sstevel@tonic-gate 		    calloc(1, sizeof (challoc))) == NULL) {
8720Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
8730Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
8740Sstevel@tonic-gate 			goto out;
8750Sstevel@tonic-gate 		}
8760Sstevel@tonic-gate 		memcpy(rc, &challoc, sizeof (challoc));
8770Sstevel@tonic-gate 		break;
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 	case CACHEFS_LOG_NOCACHE:
8800Sstevel@tonic-gate 		if ((! xdr_int(xdrs, &nocache.error)) ||
8810Sstevel@tonic-gate 		    (! xdr_int(xdrs, (int *)&nocache.time)) ||
8820Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&nocache.vfsp,
8830Sstevel@tonic-gate 		    sizeof (nocache.vfsp))) ||
8840Sstevel@tonic-gate 		    (! xdr_opaque(xdrs, (caddr_t)&nocache.fid,
8850Sstevel@tonic-gate 		    sizeof (nocache.fid))) ||
8860Sstevel@tonic-gate 		    (! xdr_u_longlong_t(xdrs,
8870Sstevel@tonic-gate 		    (u_longlong_t *)&nocache.fileno))) {
8880Sstevel@tonic-gate 			stats_perror(st, SE_CORRUPT,
8890Sstevel@tonic-gate 			    gettext("Truncated nocache record"));
8900Sstevel@tonic-gate 			goto out;
8910Sstevel@tonic-gate 		}
8920Sstevel@tonic-gate 		nocache.type = *type;
8930Sstevel@tonic-gate 		if ((rc = (struct cachefs_log_nocache_record *)
8940Sstevel@tonic-gate 		    calloc(1, sizeof (nocache))) == NULL) {
8950Sstevel@tonic-gate 			stats_perror(st, SE_NOMEM,
8960Sstevel@tonic-gate 			    gettext("Cannot malloc record"));
8970Sstevel@tonic-gate 			goto out;
8980Sstevel@tonic-gate 		}
8990Sstevel@tonic-gate 		memcpy(rc, &nocache, sizeof (nocache));
9000Sstevel@tonic-gate 		break;
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 	default:
9030Sstevel@tonic-gate 		stats_perror(st, SE_CORRUPT,
9040Sstevel@tonic-gate 		    gettext("Corrupt logfile (position %x)"),
9050Sstevel@tonic-gate 		    ftell(st->st_logstream));
9060Sstevel@tonic-gate 		break;
9070Sstevel@tonic-gate 	}
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate out:
9100Sstevel@tonic-gate 	return (rc);
9110Sstevel@tonic-gate }
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate /*
9140Sstevel@tonic-gate  * convert a logfile record (read by stats_log_logfile_read()) to
9150Sstevel@tonic-gate  * ascii.  probably not for end-user consumption, but this should be
9160Sstevel@tonic-gate  * the official way to do it.
9170Sstevel@tonic-gate  */
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate char *
stats_log_record_toascii(stats_cookie_t * st,void * recp)9200Sstevel@tonic-gate stats_log_record_toascii(stats_cookie_t *st, void *recp)
9210Sstevel@tonic-gate {
9220Sstevel@tonic-gate 	int rectype = *((int *)recp);
9230Sstevel@tonic-gate 	int recerror = *((int *)recp + 1);
9240Sstevel@tonic-gate 	time_t tt = *((time_t *)((int *)recp + 2));
9250Sstevel@tonic-gate 	struct tm *tm = localtime(&tt);
9260Sstevel@tonic-gate 	char buffy[BUFSIZ], *fidstr, *fidstr2, *fidstr3;
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	struct cachefs_log_mount_record *mountp;
9290Sstevel@tonic-gate 	struct cachefs_log_umount_record *umountp;
9300Sstevel@tonic-gate 	struct cachefs_log_getpage_record *getpagep;
9310Sstevel@tonic-gate 	struct cachefs_log_readdir_record *readdirp;
9320Sstevel@tonic-gate 	struct cachefs_log_readlink_record *readlinkp;
9330Sstevel@tonic-gate 	struct cachefs_log_remove_record *removep;
9340Sstevel@tonic-gate 	struct cachefs_log_rmdir_record *rmdirp;
9350Sstevel@tonic-gate 	struct cachefs_log_truncate_record *truncatep;
9360Sstevel@tonic-gate 	struct cachefs_log_putpage_record *putpagep;
9370Sstevel@tonic-gate 	struct cachefs_log_create_record *createp;
9380Sstevel@tonic-gate 	struct cachefs_log_mkdir_record *mkdirp;
9390Sstevel@tonic-gate 	struct cachefs_log_rename_record *renamep;
9400Sstevel@tonic-gate 	struct cachefs_log_symlink_record *symlinkp;
9410Sstevel@tonic-gate 	struct cachefs_log_populate_record *populatep;
9420Sstevel@tonic-gate 	struct cachefs_log_csymlink_record *csymlinkp;
9430Sstevel@tonic-gate 	struct cachefs_log_filldir_record *filldirp;
9440Sstevel@tonic-gate 	struct cachefs_log_mdcreate_record *mdcreatep;
9450Sstevel@tonic-gate 	struct cachefs_log_gpfront_record *gpfrontp;
9460Sstevel@tonic-gate 	struct cachefs_log_rfdir_record *rfdirp;
9470Sstevel@tonic-gate 	struct cachefs_log_ualloc_record *uallocp;
9480Sstevel@tonic-gate 	struct cachefs_log_calloc_record *callocp;
9490Sstevel@tonic-gate 	struct cachefs_log_nocache_record *nocachep;
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	assert(stats_good(st));
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 	(void) sprintf(st->st_asciirec, "%2d/%-2d %2d:%.2d %2d",
9540Sstevel@tonic-gate 	    tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
9550Sstevel@tonic-gate 	    recerror);
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	switch (rectype) {
9580Sstevel@tonic-gate 	case CACHEFS_LOG_MOUNT:
9590Sstevel@tonic-gate 		mountp = (struct cachefs_log_mount_record *)recp;
9600Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
9610Sstevel@tonic-gate 		    " %-8s %llx %8x %d %d %s (%s)", "Mount", mountp->vfsp,
9620Sstevel@tonic-gate 		    mountp->flags, mountp->popsize,
9630Sstevel@tonic-gate 		    mountp->fgsize, mountp->path,
9640Sstevel@tonic-gate 		    mountp->path + mountp->pathlen + 1);
9650Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
9660Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
9670Sstevel@tonic-gate 		break;
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	case CACHEFS_LOG_UMOUNT:
9700Sstevel@tonic-gate 		umountp = (struct cachefs_log_umount_record *)recp;
9710Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy), " %-8s %llx",
9720Sstevel@tonic-gate 		    "Umount", umountp->vfsp);
9730Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
9740Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
9750Sstevel@tonic-gate 		break;
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	case CACHEFS_LOG_GETPAGE:
9780Sstevel@tonic-gate 		getpagep = (struct cachefs_log_getpage_record *)recp;
9790Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
9800Sstevel@tonic-gate 		    " %-8s %llx %s %llu %ld %llu %u",
9810Sstevel@tonic-gate 		    "Getpage",
9820Sstevel@tonic-gate 		    getpagep->vfsp, fidstr = stats_log_fmtfid(&getpagep->fid),
9830Sstevel@tonic-gate 		    getpagep->fileno,
9840Sstevel@tonic-gate 		    getpagep->uid, getpagep->offset, getpagep->len);
9850Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
9860Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
9870Sstevel@tonic-gate 		free(fidstr);
9880Sstevel@tonic-gate 		break;
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate 	case CACHEFS_LOG_READDIR:
9910Sstevel@tonic-gate 		readdirp = (struct cachefs_log_readdir_record *)recp;
9920Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
9930Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %llx %d", "Readdir",
9940Sstevel@tonic-gate 		    readdirp->vfsp, fidstr = stats_log_fmtfid(&readdirp->fid),
9950Sstevel@tonic-gate 		    readdirp->fileno,
9960Sstevel@tonic-gate 		    readdirp->uid, readdirp->offset, readdirp->eof);
9970Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
9980Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
9990Sstevel@tonic-gate 		free(fidstr);
10000Sstevel@tonic-gate 		break;
10010Sstevel@tonic-gate 
10020Sstevel@tonic-gate 	case CACHEFS_LOG_READLINK:
10030Sstevel@tonic-gate 		readlinkp = (struct cachefs_log_readlink_record *)recp;
10040Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10050Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %u", "Readlink",
10060Sstevel@tonic-gate 		    readlinkp->vfsp,
10070Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&readlinkp->fid),
10080Sstevel@tonic-gate 		    readlinkp->fileno,
10090Sstevel@tonic-gate 		    readlinkp->uid, readlinkp->length);
10100Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10110Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10120Sstevel@tonic-gate 		free(fidstr);
10130Sstevel@tonic-gate 		break;
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 	case CACHEFS_LOG_REMOVE:
10160Sstevel@tonic-gate 		removep = (struct cachefs_log_remove_record *)recp;
10170Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10180Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Remove",
10190Sstevel@tonic-gate 		    removep->vfsp, fidstr = stats_log_fmtfid(&removep->fid),
10200Sstevel@tonic-gate 		    removep->fileno,
10210Sstevel@tonic-gate 		    removep->uid);
10220Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10230Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10240Sstevel@tonic-gate 		free(fidstr);
10250Sstevel@tonic-gate 		break;
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	case CACHEFS_LOG_RMDIR:
10280Sstevel@tonic-gate 		rmdirp = (struct cachefs_log_rmdir_record *)recp;
10290Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10300Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Rmdir",
10310Sstevel@tonic-gate 		    rmdirp->vfsp, fidstr = stats_log_fmtfid(&rmdirp->fid),
10320Sstevel@tonic-gate 		    rmdirp->fileno,
10330Sstevel@tonic-gate 		    rmdirp->uid);
10340Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10350Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10360Sstevel@tonic-gate 		free(fidstr);
10370Sstevel@tonic-gate 		break;
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 	case CACHEFS_LOG_TRUNCATE:
10400Sstevel@tonic-gate 		truncatep = (struct cachefs_log_truncate_record *)recp;
10410Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10420Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %llu", "Truncate",
10430Sstevel@tonic-gate 		    truncatep->vfsp,
10440Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&truncatep->fid),
10450Sstevel@tonic-gate 		    truncatep->fileno,
10460Sstevel@tonic-gate 		    truncatep->uid, truncatep->size);
10470Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10480Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10490Sstevel@tonic-gate 		free(fidstr);
10500Sstevel@tonic-gate 		break;
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 	case CACHEFS_LOG_PUTPAGE:
10530Sstevel@tonic-gate 		putpagep = (struct cachefs_log_putpage_record *)recp;
10540Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10550Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %llu %u", "Putpage",
10560Sstevel@tonic-gate 		    putpagep->vfsp, fidstr = stats_log_fmtfid(&putpagep->fid),
10570Sstevel@tonic-gate 		    putpagep->fileno,
10580Sstevel@tonic-gate 		    putpagep->uid, putpagep->offset, putpagep->len);
10590Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10600Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10610Sstevel@tonic-gate 		free(fidstr);
10620Sstevel@tonic-gate 		break;
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	case CACHEFS_LOG_CREATE:
10650Sstevel@tonic-gate 		createp = (struct cachefs_log_create_record *)recp;
10660Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10670Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Create",
10680Sstevel@tonic-gate 		    createp->vfsp,
10690Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&createp->fid),
10700Sstevel@tonic-gate 		    createp->fileno,
10710Sstevel@tonic-gate 		    createp->uid);
10720Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10730Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10740Sstevel@tonic-gate 		free(fidstr);
10750Sstevel@tonic-gate 		break;
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	case CACHEFS_LOG_MKDIR:
10780Sstevel@tonic-gate 		mkdirp = (struct cachefs_log_mkdir_record *)recp;
10790Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10800Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Mkdir",
10810Sstevel@tonic-gate 		    mkdirp->vfsp,
10820Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&mkdirp->fid),
10830Sstevel@tonic-gate 		    mkdirp->fileno,
10840Sstevel@tonic-gate 		    mkdirp->uid);
10850Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10860Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
10870Sstevel@tonic-gate 		free(fidstr);
10880Sstevel@tonic-gate 		break;
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	case CACHEFS_LOG_RENAME:
10910Sstevel@tonic-gate 		renamep = (struct cachefs_log_rename_record *)recp;
10920Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
10930Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %d", "Rename",
10940Sstevel@tonic-gate 		    renamep->vfsp,
10950Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&renamep->gone),
10960Sstevel@tonic-gate 		    renamep->fileno,
10970Sstevel@tonic-gate 		    renamep->removed, renamep->uid);
10980Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
10990Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11000Sstevel@tonic-gate 		free(fidstr);
11010Sstevel@tonic-gate 		break;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	case CACHEFS_LOG_SYMLINK:
11040Sstevel@tonic-gate 		symlinkp = (struct cachefs_log_symlink_record *)recp;
11050Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11060Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %u", "Symlink",
11070Sstevel@tonic-gate 		    symlinkp->vfsp,
11080Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&symlinkp->fid),
11090Sstevel@tonic-gate 		    symlinkp->fileno,
11100Sstevel@tonic-gate 		    symlinkp->uid, symlinkp->size);
11110Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11120Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11130Sstevel@tonic-gate 		free(fidstr);
11140Sstevel@tonic-gate 		break;
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	case CACHEFS_LOG_POPULATE:
11170Sstevel@tonic-gate 		populatep = (struct cachefs_log_populate_record *)recp;
11180Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11190Sstevel@tonic-gate 		    " %-8s %llx %s %llu %llu %d", "Populate",
11200Sstevel@tonic-gate 		    populatep->vfsp,
11210Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&populatep->fid),
11220Sstevel@tonic-gate 		    populatep->fileno,
11230Sstevel@tonic-gate 		    populatep->off, populatep->size);
11240Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11250Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11260Sstevel@tonic-gate 		free(fidstr);
11270Sstevel@tonic-gate 		break;
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 	case CACHEFS_LOG_CSYMLINK:
11300Sstevel@tonic-gate 		csymlinkp = (struct cachefs_log_csymlink_record *)recp;
11310Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11320Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Csymlink",
11330Sstevel@tonic-gate 		    csymlinkp->vfsp,
11340Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&csymlinkp->fid),
11350Sstevel@tonic-gate 		    csymlinkp->fileno,
11360Sstevel@tonic-gate 		    csymlinkp->size);
11370Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11380Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11390Sstevel@tonic-gate 		free(fidstr);
11400Sstevel@tonic-gate 		break;
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	case CACHEFS_LOG_FILLDIR:
11430Sstevel@tonic-gate 		filldirp = (struct cachefs_log_filldir_record *)recp;
11440Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11450Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Filldir",
11460Sstevel@tonic-gate 		    filldirp->vfsp,
11470Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&filldirp->fid),
11480Sstevel@tonic-gate 		    filldirp->fileno,
11490Sstevel@tonic-gate 		    filldirp->size);
11500Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11510Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11520Sstevel@tonic-gate 		free(fidstr);
11530Sstevel@tonic-gate 		break;
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 	case CACHEFS_LOG_MDCREATE:
11560Sstevel@tonic-gate 		mdcreatep = (struct cachefs_log_mdcreate_record *)recp;
11570Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11580Sstevel@tonic-gate 		    " %-8s %llx %s %llu %u", "Mdcreate",
11590Sstevel@tonic-gate 		    mdcreatep->vfsp,
11600Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&mdcreatep->fid),
11610Sstevel@tonic-gate 		    mdcreatep->fileno, mdcreatep->count);
11620Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11630Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11640Sstevel@tonic-gate 		free(fidstr);
11650Sstevel@tonic-gate 		break;
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 	case CACHEFS_LOG_GPFRONT:
11680Sstevel@tonic-gate 		gpfrontp = (struct cachefs_log_gpfront_record *)recp;
11690Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11700Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d %llu %u", "Gpfront",
11710Sstevel@tonic-gate 		    gpfrontp->vfsp,
11720Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&gpfrontp->fid),
11730Sstevel@tonic-gate 		    gpfrontp->fileno,
11740Sstevel@tonic-gate 		    gpfrontp->uid, gpfrontp->off, gpfrontp->len);
11750Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11760Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11770Sstevel@tonic-gate 		free(fidstr);
11780Sstevel@tonic-gate 		break;
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate 	case CACHEFS_LOG_RFDIR:
11810Sstevel@tonic-gate 		rfdirp = (struct cachefs_log_rfdir_record *)recp;
11820Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11830Sstevel@tonic-gate 		    " %-8s %llx %s %llu %d", "Rfdir",
11840Sstevel@tonic-gate 		    rfdirp->vfsp,
11850Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&rfdirp->fid),
11860Sstevel@tonic-gate 		    rfdirp->fileno,
11870Sstevel@tonic-gate 		    rfdirp->uid);
11880Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
11890Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
11900Sstevel@tonic-gate 		free(fidstr);
11910Sstevel@tonic-gate 		break;
11920Sstevel@tonic-gate 
11930Sstevel@tonic-gate 	case CACHEFS_LOG_UALLOC:
11940Sstevel@tonic-gate 		uallocp = (struct cachefs_log_ualloc_record *)recp;
11950Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
11960Sstevel@tonic-gate 		    " %-8s %llx %s %llu %llu %u", "Ualloc",
11970Sstevel@tonic-gate 		    uallocp->vfsp,
11980Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&uallocp->fid),
11990Sstevel@tonic-gate 		    uallocp->fileno,
12000Sstevel@tonic-gate 		    uallocp->off, uallocp->len);
12010Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
12020Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
12030Sstevel@tonic-gate 		free(fidstr);
12040Sstevel@tonic-gate 		break;
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 	case CACHEFS_LOG_CALLOC:
12070Sstevel@tonic-gate 		callocp = (struct cachefs_log_calloc_record *)recp;
12080Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
12090Sstevel@tonic-gate 		    " %-8s %llx %s %llu %llu %u", "Calloc",
12100Sstevel@tonic-gate 		    callocp->vfsp,
12110Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&callocp->fid),
12120Sstevel@tonic-gate 		    callocp->fileno, callocp->off, callocp->len);
12130Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
12140Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
12150Sstevel@tonic-gate 		free(fidstr);
12160Sstevel@tonic-gate 		break;
12170Sstevel@tonic-gate 
12180Sstevel@tonic-gate 	case CACHEFS_LOG_NOCACHE:
12190Sstevel@tonic-gate 		nocachep = (struct cachefs_log_nocache_record *)recp;
12200Sstevel@tonic-gate 		(void) snprintf(buffy, sizeof (buffy),
12210Sstevel@tonic-gate 		    " %-8s %llx %s %llu", "Nocache",
12220Sstevel@tonic-gate 		    nocachep->vfsp,
12230Sstevel@tonic-gate 		    fidstr = stats_log_fmtfid(&nocachep->fid),
12240Sstevel@tonic-gate 		    nocachep->fileno);
12250Sstevel@tonic-gate 		(void) strlcat(st->st_asciirec, buffy,
12260Sstevel@tonic-gate 		    sizeof (st->st_asciirec));
12270Sstevel@tonic-gate 		free(fidstr);
12280Sstevel@tonic-gate 		break;
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 	default:
12310Sstevel@tonic-gate 		stats_perror(st, SE_CORRUPT,
12320Sstevel@tonic-gate 		    gettext(
12330Sstevel@tonic-gate 		    "Attempt to format invalid log type=%d (position %x)"),
12340Sstevel@tonic-gate 		    rectype, ftell(st->st_logstream));
12350Sstevel@tonic-gate 		return (NULL);
12360Sstevel@tonic-gate 	}
12370Sstevel@tonic-gate 
12380Sstevel@tonic-gate 	return (st->st_asciirec);
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate uint_t
stats_log_get_record_info(stats_cookie_t * sc,void * recp,caddr_t * vfsp,cfs_fid_t ** fidp,ino64_t * filenop,u_offset_t * offp,u_offset_t * lenp)12420Sstevel@tonic-gate stats_log_get_record_info(stats_cookie_t *sc,
12430Sstevel@tonic-gate     void *recp, caddr_t *vfsp, cfs_fid_t **fidp, ino64_t *filenop,
12440Sstevel@tonic-gate     u_offset_t *offp, u_offset_t *lenp)
12450Sstevel@tonic-gate {
12460Sstevel@tonic-gate 	int type = ((int *)recp)[0];
12470Sstevel@tonic-gate 	int error = ((int *)recp)[1];
12480Sstevel@tonic-gate 	uint_t rc = 0;
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	struct cachefs_log_getpage_record *getpagep;
12510Sstevel@tonic-gate 	struct cachefs_log_readdir_record *readdirp;
12520Sstevel@tonic-gate 	struct cachefs_log_readlink_record *readlinkp;
12530Sstevel@tonic-gate 	struct cachefs_log_remove_record *removep;
12540Sstevel@tonic-gate 	struct cachefs_log_rmdir_record *rmdirp;
12550Sstevel@tonic-gate 	struct cachefs_log_truncate_record *truncatep;
12560Sstevel@tonic-gate 	struct cachefs_log_putpage_record *putpagep;
12570Sstevel@tonic-gate 	struct cachefs_log_create_record *createp;
12580Sstevel@tonic-gate 	struct cachefs_log_mkdir_record *mkdirp;
12590Sstevel@tonic-gate 	struct cachefs_log_rename_record *renamep;
12600Sstevel@tonic-gate 	struct cachefs_log_symlink_record *symlinkp;
12610Sstevel@tonic-gate 	struct cachefs_log_populate_record *populatep;
12620Sstevel@tonic-gate 	struct cachefs_log_csymlink_record *csymlinkp;
12630Sstevel@tonic-gate 	struct cachefs_log_filldir_record *filldirp;
12640Sstevel@tonic-gate 	struct cachefs_log_mdcreate_record *mdcreatep;
12650Sstevel@tonic-gate 	struct cachefs_log_gpfront_record *gpfrontp;
12660Sstevel@tonic-gate 	struct cachefs_log_rfdir_record *rfdirp;
12670Sstevel@tonic-gate 	struct cachefs_log_ualloc_record *uallocp;
12680Sstevel@tonic-gate 	struct cachefs_log_calloc_record *callocp;
12690Sstevel@tonic-gate 	struct cachefs_log_nocache_record *nocachep;
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate 	switch (type) {
12720Sstevel@tonic-gate 	case CACHEFS_LOG_RFDIR:
12730Sstevel@tonic-gate 		if ((error == EINVAL) || (error == ENOENT))
12740Sstevel@tonic-gate 			error = 0;
12750Sstevel@tonic-gate 		break;
12760Sstevel@tonic-gate 	}
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	if (error != 0)
12790Sstevel@tonic-gate 		return (0);
12800Sstevel@tonic-gate 
12810Sstevel@tonic-gate 	switch (type) {
12820Sstevel@tonic-gate 	case CACHEFS_LOG_GETPAGE:
12830Sstevel@tonic-gate 		getpagep = (struct cachefs_log_getpage_record *)recp;
12840Sstevel@tonic-gate 		*fidp = &getpagep->fid;
12850Sstevel@tonic-gate 		*filenop = getpagep->fileno;
1286*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)getpagep->vfsp;
12870Sstevel@tonic-gate 		*offp = getpagep->offset;
12880Sstevel@tonic-gate 		*lenp = (u_offset_t)getpagep->len;
12890Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_EXPENSIVE);
12900Sstevel@tonic-gate 		break;
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 	case CACHEFS_LOG_READDIR:
12930Sstevel@tonic-gate 		readdirp = (struct cachefs_log_readdir_record *)recp;
12940Sstevel@tonic-gate 		*fidp = &readdirp->fid;
12950Sstevel@tonic-gate 		*filenop = readdirp->fileno;
1296*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)readdirp->vfsp;
12970Sstevel@tonic-gate 		*offp = readdirp->offset;
12980Sstevel@tonic-gate 		*lenp = (u_offset_t)sc->st_loghead.lh_maxbsize;
12990Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_EXPENSIVE);
13000Sstevel@tonic-gate 		break;
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate 	case CACHEFS_LOG_READLINK:
13030Sstevel@tonic-gate 		readlinkp = (struct cachefs_log_readlink_record *)recp;
13040Sstevel@tonic-gate 		*fidp = &readlinkp->fid;
13050Sstevel@tonic-gate 		*filenop = readlinkp->fileno;
1306*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)readlinkp->vfsp;
13070Sstevel@tonic-gate 		*offp = 0LL;
13080Sstevel@tonic-gate 		*lenp = (u_offset_t)((readlinkp->length > C_FSL_SIZE) ?
13090Sstevel@tonic-gate 		    readlinkp->length : 0);
13100Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_EXPENSIVE);
13110Sstevel@tonic-gate 		break;
13120Sstevel@tonic-gate 
13130Sstevel@tonic-gate 	case CACHEFS_LOG_REMOVE:
13140Sstevel@tonic-gate 		removep = (struct cachefs_log_remove_record *)recp;
13150Sstevel@tonic-gate 		*fidp = &removep->fid;
13160Sstevel@tonic-gate 		*filenop = removep->fileno;
1317*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)removep->vfsp;
13180Sstevel@tonic-gate 		*offp = *lenp = 0LL;
13190Sstevel@tonic-gate 		rc = (GRI_TRUNC | GRI_MODIFY);
13200Sstevel@tonic-gate 		break;
13210Sstevel@tonic-gate 
13220Sstevel@tonic-gate 	case CACHEFS_LOG_RMDIR:
13230Sstevel@tonic-gate 		rmdirp = (struct cachefs_log_rmdir_record *)recp;
13240Sstevel@tonic-gate 		*fidp = &rmdirp->fid;
13250Sstevel@tonic-gate 		*filenop = rmdirp->fileno;
1326*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)rmdirp->vfsp;
13270Sstevel@tonic-gate 		*offp = *lenp = 0LL;
13280Sstevel@tonic-gate 		rc = (GRI_TRUNC | GRI_MODIFY);
13290Sstevel@tonic-gate 		break;
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 	case CACHEFS_LOG_TRUNCATE:
13320Sstevel@tonic-gate 		truncatep = (struct cachefs_log_truncate_record *)recp;
13330Sstevel@tonic-gate 		*fidp = &truncatep->fid;
13340Sstevel@tonic-gate 		*filenop = truncatep->fileno;
1335*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)truncatep->vfsp;
13360Sstevel@tonic-gate 		*offp = 0LL;
13370Sstevel@tonic-gate 		*lenp = truncatep->size;
13380Sstevel@tonic-gate 		rc = (GRI_TRUNC | GRI_MODIFY);
13390Sstevel@tonic-gate 		break;
13400Sstevel@tonic-gate 
13410Sstevel@tonic-gate 	case CACHEFS_LOG_PUTPAGE:
13420Sstevel@tonic-gate 		putpagep = (struct cachefs_log_putpage_record *)recp;
13430Sstevel@tonic-gate 		*fidp = &putpagep->fid;
13440Sstevel@tonic-gate 		*filenop = putpagep->fileno;
1345*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)putpagep->vfsp;
13460Sstevel@tonic-gate 		*offp = putpagep->offset;
13470Sstevel@tonic-gate 		*lenp = (u_offset_t)putpagep->len;
13480Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_MODIFY);
13490Sstevel@tonic-gate 		break;
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	case CACHEFS_LOG_CREATE:
13520Sstevel@tonic-gate 		createp = (struct cachefs_log_create_record *)recp;
13530Sstevel@tonic-gate 		*fidp = &createp->fid;
13540Sstevel@tonic-gate 		*filenop = createp->fileno;
1355*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)createp->vfsp;
13560Sstevel@tonic-gate 		*offp = *lenp = 0LL;
13570Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_MODIFY);
13580Sstevel@tonic-gate 		break;
13590Sstevel@tonic-gate 
13600Sstevel@tonic-gate 	case CACHEFS_LOG_MKDIR:
13610Sstevel@tonic-gate 		mkdirp = (struct cachefs_log_mkdir_record *)recp;
13620Sstevel@tonic-gate 		*fidp = &mkdirp->fid;
13630Sstevel@tonic-gate 		*filenop = mkdirp->fileno;
1364*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)mkdirp->vfsp;
13650Sstevel@tonic-gate 		*offp = *lenp = 0LL;
13660Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_MODIFY);
13670Sstevel@tonic-gate 		break;
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	case CACHEFS_LOG_RENAME:
13700Sstevel@tonic-gate 		renamep = (struct cachefs_log_rename_record *)recp;
13710Sstevel@tonic-gate 		*fidp = &renamep->gone;
13720Sstevel@tonic-gate 		*filenop = renamep->fileno;
1373*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)renamep->vfsp;
13740Sstevel@tonic-gate 		*offp = *lenp = 0LL;
13750Sstevel@tonic-gate 		rc = GRI_MODIFY;
13760Sstevel@tonic-gate 		if (renamep->removed)
13770Sstevel@tonic-gate 			rc |= GRI_TRUNC;
13780Sstevel@tonic-gate 		break;
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 	case CACHEFS_LOG_SYMLINK:
13810Sstevel@tonic-gate 		symlinkp = (struct cachefs_log_symlink_record *)recp;
13820Sstevel@tonic-gate 		*fidp = &symlinkp->fid;
13830Sstevel@tonic-gate 		*filenop = symlinkp->fileno;
1384*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)symlinkp->vfsp;
13850Sstevel@tonic-gate 		*offp = 0LL;
13860Sstevel@tonic-gate 		*lenp = (u_offset_t)((symlinkp->size > C_FSL_SIZE) ?
13870Sstevel@tonic-gate 		    symlinkp->size : 0);
13880Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_MODIFY);
13890Sstevel@tonic-gate 		break;
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 	case CACHEFS_LOG_POPULATE:
13920Sstevel@tonic-gate 		populatep = (struct cachefs_log_populate_record *)recp;
13930Sstevel@tonic-gate 		*fidp = &populatep->fid;
13940Sstevel@tonic-gate 		*filenop = populatep->fileno;
1395*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)populatep->vfsp;
13960Sstevel@tonic-gate 		*offp = populatep->off;
13970Sstevel@tonic-gate 		*lenp = (u_offset_t)populatep->size;
13980Sstevel@tonic-gate 		rc = GRI_ADD;
13990Sstevel@tonic-gate 		break;
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	case CACHEFS_LOG_CSYMLINK:
14020Sstevel@tonic-gate 		csymlinkp = (struct cachefs_log_csymlink_record *)recp;
14030Sstevel@tonic-gate 		*fidp = &csymlinkp->fid;
14040Sstevel@tonic-gate 		*filenop = csymlinkp->fileno;
1405*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)csymlinkp->vfsp;
14060Sstevel@tonic-gate 		*offp = 0LL;
14070Sstevel@tonic-gate 		*lenp = (u_offset_t)((csymlinkp->size > C_FSL_SIZE) ?
14080Sstevel@tonic-gate 		    csymlinkp->size : 0);
14090Sstevel@tonic-gate 		rc = GRI_ADD;
14100Sstevel@tonic-gate 		break;
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	case CACHEFS_LOG_FILLDIR:
14130Sstevel@tonic-gate 		filldirp = (struct cachefs_log_filldir_record *)recp;
14140Sstevel@tonic-gate 		*fidp = &filldirp->fid;
14150Sstevel@tonic-gate 		*filenop = filldirp->fileno;
1416*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)filldirp->vfsp;
14170Sstevel@tonic-gate 		*offp = 0LL;
14180Sstevel@tonic-gate 		*lenp = (u_offset_t)(filldirp->size);
14190Sstevel@tonic-gate 		rc = GRI_ADD;
14200Sstevel@tonic-gate 		break;
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate 	case CACHEFS_LOG_MDCREATE:
14230Sstevel@tonic-gate 		mdcreatep = (struct cachefs_log_mdcreate_record *)recp;
14240Sstevel@tonic-gate 		*fidp = &mdcreatep->fid;
14250Sstevel@tonic-gate 		*filenop = mdcreatep->fileno;
1426*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)mdcreatep->vfsp;
14270Sstevel@tonic-gate 		*lenp = (u_offset_t)mdcreatep->count;
14280Sstevel@tonic-gate 		rc = GRI_METADATA;
14290Sstevel@tonic-gate 		break;
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 	case CACHEFS_LOG_GPFRONT:
14320Sstevel@tonic-gate 		gpfrontp = (struct cachefs_log_gpfront_record *)recp;
14330Sstevel@tonic-gate 		*fidp = &gpfrontp->fid;
14340Sstevel@tonic-gate 		*filenop = gpfrontp->fileno;
1435*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)gpfrontp->vfsp;
14360Sstevel@tonic-gate 		*offp = gpfrontp->off;
14370Sstevel@tonic-gate 		*lenp = (u_offset_t)sc->st_loghead.lh_pagesize;
14380Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_EXPENSIVE);
14390Sstevel@tonic-gate 		break;
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 	case CACHEFS_LOG_RFDIR:
14420Sstevel@tonic-gate 		rfdirp = (struct cachefs_log_rfdir_record *)recp;
14430Sstevel@tonic-gate 		rfdirp->error = 0;
14440Sstevel@tonic-gate 		*fidp = &rfdirp->fid;
14450Sstevel@tonic-gate 		*filenop = rfdirp->fileno;
1446*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)rfdirp->vfsp;
14470Sstevel@tonic-gate 		*offp = 0LL;
14480Sstevel@tonic-gate 		*lenp = (u_offset_t)sc->st_loghead.lh_maxbsize;
14490Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_EXPENSIVE);
14500Sstevel@tonic-gate 		break;
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 	case CACHEFS_LOG_UALLOC:
14530Sstevel@tonic-gate 		uallocp = (struct cachefs_log_ualloc_record *)recp;
14540Sstevel@tonic-gate 		*fidp = &uallocp->fid;
14550Sstevel@tonic-gate 		*filenop = uallocp->fileno;
1456*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)uallocp->vfsp;
14570Sstevel@tonic-gate 		*offp = uallocp->off;
14580Sstevel@tonic-gate 		*lenp = (u_offset_t)uallocp->len;
14590Sstevel@tonic-gate 		rc = (GRI_ADD);
14600Sstevel@tonic-gate 		break;
14610Sstevel@tonic-gate 
14620Sstevel@tonic-gate 	case CACHEFS_LOG_CALLOC:
14630Sstevel@tonic-gate 		callocp = (struct cachefs_log_calloc_record *)recp;
14640Sstevel@tonic-gate 		*fidp = &callocp->fid;
14650Sstevel@tonic-gate 		*filenop = callocp->fileno;
1466*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)callocp->vfsp;
14670Sstevel@tonic-gate 		*offp = callocp->off;
14680Sstevel@tonic-gate 		*lenp = (u_offset_t)callocp->len;
14690Sstevel@tonic-gate 		rc = (GRI_ADD | GRI_EXPENSIVE);
14700Sstevel@tonic-gate 		break;
14710Sstevel@tonic-gate 
14720Sstevel@tonic-gate 	case CACHEFS_LOG_NOCACHE:
14730Sstevel@tonic-gate 		nocachep = (struct cachefs_log_nocache_record *)recp;
14740Sstevel@tonic-gate 		*fidp = &nocachep->fid;
14750Sstevel@tonic-gate 		*filenop = nocachep->fileno;
1476*633Sgt29601 		*vfsp = (caddr_t)(uintptr_t)nocachep->vfsp;
14770Sstevel@tonic-gate 		*offp = *lenp = 0LL;
14780Sstevel@tonic-gate 		rc = (GRI_TRUNC);
14790Sstevel@tonic-gate 		break;
14800Sstevel@tonic-gate 	}
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	return (rc);
14830Sstevel@tonic-gate }
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate /*
14860Sstevel@tonic-gate  * ascii formatter for fids.  returns a malloc()ed string -- it's up to
14870Sstevel@tonic-gate  * the caller to free it.
14880Sstevel@tonic-gate  */
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate static char *
stats_log_fmtfid(cfs_fid_t * fidp)14910Sstevel@tonic-gate stats_log_fmtfid(cfs_fid_t *fidp)
14920Sstevel@tonic-gate {
14930Sstevel@tonic-gate 	char buffy[BUFSIZ], *rc;
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate (void) strcpy(buffy, "<fid>");
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 	rc = strdup(buffy);
14980Sstevel@tonic-gate 	if (rc == NULL)
14990Sstevel@tonic-gate 		rc = "out of memory";
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 	return (rc);
15020Sstevel@tonic-gate }
15030Sstevel@tonic-gate 
15040Sstevel@tonic-gate void
stats_log_fi_add(stats_cookie_t * st,fid_info * fip,u_offset_t off,u_offset_t len)15050Sstevel@tonic-gate stats_log_fi_add(stats_cookie_t *st, fid_info *fip, u_offset_t off,
15060Sstevel@tonic-gate u_offset_t len)
15070Sstevel@tonic-gate {
15080Sstevel@tonic-gate 	int i, j;
15090Sstevel@tonic-gate 	u_offset_t iend, jend, tmp;
15100Sstevel@tonic-gate 
15110Sstevel@tonic-gate 	assert(stats_good(st));
15120Sstevel@tonic-gate 	assert(st->st_flags & ST_DBMOPEN);
15130Sstevel@tonic-gate 	assert(st->st_flags & ST_LFOPEN);
15140Sstevel@tonic-gate 
15150Sstevel@tonic-gate 	/* shortcut if we had some sort of zero-length thing */
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	if (len == 0LL)
15180Sstevel@tonic-gate 		return;
15190Sstevel@tonic-gate 
15200Sstevel@tonic-gate 	/* `smear' the offset and length to block boundaries */
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate 	/*
15230Sstevel@tonic-gate 	 * pre-largefiles: iend = off & ~(st->st_loghead.lh_maxbsize - 1);
15240Sstevel@tonic-gate 	 * largefiles:  make sure that we ~ all bits in the 64 bit
15250Sstevel@tonic-gate 	 * version of (st->st_loghead.lh_maxbsize - 1)
15260Sstevel@tonic-gate 	 */
15270Sstevel@tonic-gate 	tmp = (u_offset_t)(st->st_loghead.lh_maxbsize - 1);
15280Sstevel@tonic-gate 	iend = off & ~tmp;
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	jend = off + len;
15310Sstevel@tonic-gate 	jend += (u_offset_t)(st->st_loghead.lh_maxbsize - 1);
15320Sstevel@tonic-gate 	/*
15330Sstevel@tonic-gate 	 * pre-largefiles:  jend &= ~(st->st_loghead.lh_maxbsize - 1);
15340Sstevel@tonic-gate 	 * largefiles: make sure that we ~ all bits in the 64 bit
15350Sstevel@tonic-gate 	 * version of (st->st_loghead.lh_maxbsize - 1)
15360Sstevel@tonic-gate 	 */
15370Sstevel@tonic-gate 	jend &= ~tmp;
15380Sstevel@tonic-gate 
15390Sstevel@tonic-gate 	off = iend;
15400Sstevel@tonic-gate 	len = jend - off;
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	/* see if our offset falls within an existing chunk */
15430Sstevel@tonic-gate 	for (i = 0; i < fip->fi_ent_n; i++) {
15440Sstevel@tonic-gate 		iend = fip->fi_ent[i].offset + fip->fi_ent[i].len;
15450Sstevel@tonic-gate 		if ((fip->fi_ent[i].offset <= off) && (iend >= off))
15460Sstevel@tonic-gate 			break;
15470Sstevel@tonic-gate 	}
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 	/* update the chunk, or make a new one */
15500Sstevel@tonic-gate 	if (i < fip->fi_ent_n) {
15510Sstevel@tonic-gate 		if ((off + len) > iend)
15520Sstevel@tonic-gate 			fip->fi_ent[i].len = off + len - fip->fi_ent[i].offset;
15530Sstevel@tonic-gate 	} else if (i < C_MAX_ALLOCINFO_SLOTS) {
15540Sstevel@tonic-gate 		fip->fi_ent_n = i + 1;
15550Sstevel@tonic-gate 		fip->fi_ent[i].offset = off;
15560Sstevel@tonic-gate 		fip->fi_ent[i].len = len;
15570Sstevel@tonic-gate 	} else {
15580Sstevel@tonic-gate 		/* cachefs does a nocache, so we'll immitate */
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 		/*
15610Sstevel@tonic-gate 		 * XXX we're free to grow again.  assume we got
15620Sstevel@tonic-gate 		 * inactivated right away -- the worst case!
15630Sstevel@tonic-gate 		 */
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate 		fip->fi_ent_n = 0;
15660Sstevel@tonic-gate 		fip->fi_total = 0LL;
15670Sstevel@tonic-gate 	}
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 	/* quit for the trivial (hopefully the usual) case... */
15700Sstevel@tonic-gate 	if (fip->fi_ent_n <= 1) {
15710Sstevel@tonic-gate 		if (fip->fi_ent_n == 0)
15720Sstevel@tonic-gate 			fip->fi_total = 0LL;
15730Sstevel@tonic-gate 		else
15740Sstevel@tonic-gate 			fip->fi_total = fip->fi_ent[0].len;
15750Sstevel@tonic-gate 		return;
15760Sstevel@tonic-gate 	}
15770Sstevel@tonic-gate 
15780Sstevel@tonic-gate 	/*
15790Sstevel@tonic-gate 	 * we have to see if we can consolidate any chunks.  the
15800Sstevel@tonic-gate 	 * chunks aren't guaranteed to be in any kind of order, so we
15810Sstevel@tonic-gate 	 * do a qsort.  otherwise, the consolidation would be N^2 (but
15820Sstevel@tonic-gate 	 * we're probably close here).
15830Sstevel@tonic-gate 	 */
15840Sstevel@tonic-gate 
15850Sstevel@tonic-gate 	qsort(fip->fi_ent, fip->fi_ent_n, sizeof (fip->fi_ent[0]),
15860Sstevel@tonic-gate 	    stats_log_fi_comp);
15870Sstevel@tonic-gate 
15880Sstevel@tonic-gate 	/* tag non-essential entries with offset == -1, and consolidate */
15890Sstevel@tonic-gate 	for (i = 0; i < fip->fi_ent_n - 1; i++) {
15900Sstevel@tonic-gate 		if ((offset_t)fip->fi_ent[i].offset < 0)
15910Sstevel@tonic-gate 			continue;
15920Sstevel@tonic-gate 		iend = fip->fi_ent[i].offset + fip->fi_ent[i].len;
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 		for (j = i + 1; j < fip->fi_ent_n; j++) {
15950Sstevel@tonic-gate 			if (iend < fip->fi_ent[j].offset)
15960Sstevel@tonic-gate 				break;
15970Sstevel@tonic-gate 			jend = fip->fi_ent[j].offset + fip->fi_ent[j].len;
15980Sstevel@tonic-gate 			if (jend >= iend)
15990Sstevel@tonic-gate 				fip->fi_ent[i].len =
16000Sstevel@tonic-gate 				    jend - fip->fi_ent[i].offset;
16010Sstevel@tonic-gate 			fip->fi_ent[j].offset = (u_offset_t)-1;
16020Sstevel@tonic-gate 		}
16030Sstevel@tonic-gate 	}
16040Sstevel@tonic-gate 
16050Sstevel@tonic-gate 	/* get rid of non-essential entries (without preserving order) */
16060Sstevel@tonic-gate 	for (i = 0; i < fip->fi_ent_n; i++)
16070Sstevel@tonic-gate 		if ((offset_t)fip->fi_ent[i].offset < 0)
16080Sstevel@tonic-gate 			fip->fi_ent[i--] = fip->fi_ent[--(fip->fi_ent_n)];
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate 	/* add up the new total size */
16110Sstevel@tonic-gate 	for (i = fip->fi_total = 0LL; i < fip->fi_ent_n; i++)
16120Sstevel@tonic-gate 		fip->fi_total += fip->fi_ent[i].len;
16130Sstevel@tonic-gate }
16140Sstevel@tonic-gate 
16150Sstevel@tonic-gate static int
stats_log_fi_comp(const void * a,const void * b)16160Sstevel@tonic-gate stats_log_fi_comp(const void *a, const void *b)
16170Sstevel@tonic-gate {
16180Sstevel@tonic-gate 	struct fid_info_allocent *fa = (struct fid_info_allocent *)a;
16190Sstevel@tonic-gate 	struct fid_info_allocent *fb = (struct fid_info_allocent *)b;
16200Sstevel@tonic-gate 
16210Sstevel@tonic-gate 	if ((offset_t)(fa->offset - fb->offset) > 0)
16220Sstevel@tonic-gate 		return (1);
16230Sstevel@tonic-gate 	if ((offset_t)(fa->offset - fb->offset) < 0)
16240Sstevel@tonic-gate 		return (-1);
16250Sstevel@tonic-gate 	return (0);
16260Sstevel@tonic-gate }
16270Sstevel@tonic-gate 
16280Sstevel@tonic-gate void
stats_log_fi_trunc(stats_cookie_t * st,fid_info * fip,u_offset_t off,u_offset_t len)16290Sstevel@tonic-gate stats_log_fi_trunc(stats_cookie_t *st, fid_info *fip, u_offset_t off,
16300Sstevel@tonic-gate u_offset_t len)
16310Sstevel@tonic-gate {
16320Sstevel@tonic-gate 	fip->fi_ent_n = 1;
16330Sstevel@tonic-gate 	fip->fi_ent[0].offset = off;
16340Sstevel@tonic-gate 	fip->fi_ent[0].len = len;
16350Sstevel@tonic-gate 	fip->fi_total = len;
16360Sstevel@tonic-gate }
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate struct cachefs_log_logfile_header *
stats_log_getheader(stats_cookie_t * st)16390Sstevel@tonic-gate stats_log_getheader(stats_cookie_t *st)
16400Sstevel@tonic-gate {
16410Sstevel@tonic-gate 	assert(stats_good(st));
16420Sstevel@tonic-gate 	assert(st->st_flags & ST_LFOPEN);
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 	return (&st->st_loghead);
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate 
16470Sstevel@tonic-gate void
stats_log_compute_wssize(stats_cookie_t * st)16480Sstevel@tonic-gate stats_log_compute_wssize(stats_cookie_t *st)
16490Sstevel@tonic-gate {
16500Sstevel@tonic-gate 	void *record;
16510Sstevel@tonic-gate 	int type;
16520Sstevel@tonic-gate 	struct cachefs_log_mount_record *mountp;
16530Sstevel@tonic-gate 	struct cachefs_log_umount_record *umountp;
16540Sstevel@tonic-gate 	datum key;
16550Sstevel@tonic-gate 	caddr_t vfsp;
16560Sstevel@tonic-gate 	mount_info *mi = NULL, *mip;
16570Sstevel@tonic-gate 	size_t len1, len2, maxlen;
16580Sstevel@tonic-gate 	char *string1, *string2;
16590Sstevel@tonic-gate 	uint_t rflags;
16600Sstevel@tonic-gate 	fid_info fi, *fip;
16610Sstevel@tonic-gate 	cfs_fid_t *fidp;
16620Sstevel@tonic-gate 	ino64_t fileno;
16630Sstevel@tonic-gate 	u_offset_t off;
16640Sstevel@tonic-gate 	u_offset_t len;
16650Sstevel@tonic-gate 	struct cachefs_log_logfile_header *lh = &st->st_loghead;
16660Sstevel@tonic-gate 	size_t delta;
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 	assert(stats_good(st));
16690Sstevel@tonic-gate 	assert(st->st_flags & ST_LFOPEN);
16700Sstevel@tonic-gate 	assert(st->st_flags & ST_DBMOPEN);
16710Sstevel@tonic-gate 
16720Sstevel@tonic-gate 	/*
16730Sstevel@tonic-gate 	 * The maximum size of a mount_info structure is the size of
16740Sstevel@tonic-gate 	 * the structure less the space already defined for char mi_path[]
16750Sstevel@tonic-gate 	 * plus the maximum size of mi_path.
16760Sstevel@tonic-gate 	 *
16770Sstevel@tonic-gate 	 * Additional space is allocated to mi_path at runtime using
16780Sstevel@tonic-gate 	 * malloc(). The size needs to be calculated in-situ as ANSI C
16790Sstevel@tonic-gate 	 * will only allow 'sizeof expression' or 'sizeof (type)'.
16800Sstevel@tonic-gate 	 */
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate 	mi = malloc(sizeof (*mi) - sizeof (mi->mi_path) + MI_MAX_MI_PATH);
16830Sstevel@tonic-gate 	if (mi == NULL) {
16840Sstevel@tonic-gate 		stats_perror(st, SE_NOMEM, gettext("Out of memory"));
16850Sstevel@tonic-gate 		goto out;
16860Sstevel@tonic-gate 	}
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	st->st_ws_init = st->st_loghead.lh_blocks;
16890Sstevel@tonic-gate 
16900Sstevel@tonic-gate 	while (record = stats_log_logfile_read(st, &type)) {
16910Sstevel@tonic-gate 		switch (type) {
16920Sstevel@tonic-gate 		case CACHEFS_LOG_MOUNT:
16930Sstevel@tonic-gate 			mountp = (struct cachefs_log_mount_record *)record;
16940Sstevel@tonic-gate 			if (mountp->error != 0)
16950Sstevel@tonic-gate 				break;
16960Sstevel@tonic-gate 			for (key = stats_dbm_firstkey(st);
16970Sstevel@tonic-gate 			    key.dptr != NULL;
16980Sstevel@tonic-gate 			    key = stats_dbm_nextkey(st)) {
16990Sstevel@tonic-gate 				if (key.dsize != sizeof (vfsp))
17000Sstevel@tonic-gate 					continue;
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 				memcpy((caddr_t)&vfsp, key.dptr,
17030Sstevel@tonic-gate 				    sizeof (vfsp));
17040Sstevel@tonic-gate 				mip = stats_dbm_fetch_byvfsp(st, vfsp);
17050Sstevel@tonic-gate 				if (mip == NULL)
17060Sstevel@tonic-gate 					continue;
17070Sstevel@tonic-gate 
17080Sstevel@tonic-gate 				len1 = strlen(mip->mi_path);
17090Sstevel@tonic-gate 				len2 = strlen(mip->mi_path + len1 + 1);
17100Sstevel@tonic-gate 				memcpy((caddr_t)mi, mip, sizeof (*mi) +
17110Sstevel@tonic-gate 				    len1 + len2 - CLPAD(mount_info, mi_path));
17120Sstevel@tonic-gate 				free(mip);
17130Sstevel@tonic-gate 
17140Sstevel@tonic-gate 				string1 = mi->mi_path + len1 + 1;
17150Sstevel@tonic-gate 				string2 = mountp->path + mountp->pathlen + 1;
17160Sstevel@tonic-gate 				if (strcmp(string1, string2) == 0) {
17170Sstevel@tonic-gate 					stats_dbm_delete_byvfsp(st, vfsp);
17180Sstevel@tonic-gate 					break;
17190Sstevel@tonic-gate 				}
17200Sstevel@tonic-gate 			}
17210Sstevel@tonic-gate 			if (key.dptr == NULL) {
17220Sstevel@tonic-gate 				/* non-idempotent setup stuff */
17230Sstevel@tonic-gate 				memset(mi, '\0', sizeof (*mi));
17240Sstevel@tonic-gate 				mi->mi_flags = mountp->flags;
17250Sstevel@tonic-gate 				mi->mi_filegrp_size = mountp->fgsize;
17260Sstevel@tonic-gate 			}
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 			/*
17290Sstevel@tonic-gate 			 * idempotent setup stuff
17300Sstevel@tonic-gate 			 *
17310Sstevel@tonic-gate 			 * Careful string handling around mi_path
17320Sstevel@tonic-gate 			 * is required as it contains two NULL
17330Sstevel@tonic-gate 			 * terminated strings.
17340Sstevel@tonic-gate 			 */
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 			mi->mi_mounted = 1;
17370Sstevel@tonic-gate 			maxlen = MI_MAX_MI_PATH - 1;
17380Sstevel@tonic-gate 			len1 = strlcpy(mi->mi_path, mountp->path, maxlen);
17390Sstevel@tonic-gate 			if (len1 >= maxlen) {
17400Sstevel@tonic-gate 				stats_perror(st, SE_CORRUPT,
17410Sstevel@tonic-gate 				    gettext("Path too long in log file"));
17420Sstevel@tonic-gate 				break;
17430Sstevel@tonic-gate 			}
17440Sstevel@tonic-gate 
17450Sstevel@tonic-gate 			len1 = strlen(mi->mi_path);
17460Sstevel@tonic-gate 			maxlen = MI_MAX_MI_PATH - (len1 + 1);
17470Sstevel@tonic-gate 			len2 = strlcpy(mi->mi_path + len1 + 1,
17480Sstevel@tonic-gate 			    mountp->path + mountp->pathlen + 1, maxlen);
17490Sstevel@tonic-gate 			if (len2 >= maxlen) {
17500Sstevel@tonic-gate 				stats_perror(st, SE_CORRUPT,
17510Sstevel@tonic-gate 				    gettext("CacheID too long in log file"));
17520Sstevel@tonic-gate 				break;
17530Sstevel@tonic-gate 			}
17540Sstevel@tonic-gate 
1755*633Sgt29601 			stats_dbm_store_byvfsp(st,
1756*633Sgt29601 					(caddr_t)(uintptr_t)mountp->vfsp, mi);
17570Sstevel@tonic-gate 			break;
17580Sstevel@tonic-gate 
17590Sstevel@tonic-gate 		case CACHEFS_LOG_UMOUNT:
17600Sstevel@tonic-gate 			umountp = (struct cachefs_log_umount_record *)record;
17610Sstevel@tonic-gate 			if (umountp->error != 0)
17620Sstevel@tonic-gate 				break;
17630Sstevel@tonic-gate 			mip = stats_dbm_fetch_byvfsp(st,
1764*633Sgt29601 					(caddr_t)(uintptr_t)umountp->vfsp);
17650Sstevel@tonic-gate 			if (mip == NULL)
17660Sstevel@tonic-gate 				break;
17670Sstevel@tonic-gate 			mip->mi_mounted = 0;
1768*633Sgt29601 			stats_dbm_store_byvfsp(st,
1769*633Sgt29601 					(caddr_t)(uintptr_t)umountp->vfsp, mip);
17700Sstevel@tonic-gate 			free(mip);
17710Sstevel@tonic-gate 			break;
17720Sstevel@tonic-gate 
17730Sstevel@tonic-gate 		default:
17740Sstevel@tonic-gate 			rflags = stats_log_get_record_info(st, record,
17750Sstevel@tonic-gate 			    &vfsp, &fidp, &fileno, &off, &len);
17760Sstevel@tonic-gate 			if (rflags == 0) /* shortcut */
17770Sstevel@tonic-gate 				break;
17780Sstevel@tonic-gate 
17790Sstevel@tonic-gate 			mip = stats_dbm_fetch_byvfsp(st, vfsp);
17800Sstevel@tonic-gate 			if (mip == NULL) /* hopefully very rare */
17810Sstevel@tonic-gate 				break;
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 			fip = stats_dbm_fetch_byfid(st, fidp);
17840Sstevel@tonic-gate 			if (fip == NULL) {
17850Sstevel@tonic-gate 				fip = &fi;
17860Sstevel@tonic-gate 				memset(&fi, '\0', sizeof (fi));
17870Sstevel@tonic-gate 				fi.fi_vfsp = vfsp;
17880Sstevel@tonic-gate 			}
17890Sstevel@tonic-gate 
17900Sstevel@tonic-gate 			/* account for the creation of the fscache */
17910Sstevel@tonic-gate 			if (! mip->mi_used) {
17920Sstevel@tonic-gate 				mip->mi_used = 1;
17930Sstevel@tonic-gate 
17940Sstevel@tonic-gate 				/* account for the .cfs_option file */
17950Sstevel@tonic-gate 				mip->mi_current += (u_offset_t)lh->lh_maxbsize;
17960Sstevel@tonic-gate 				st->st_ws_current +=
17970Sstevel@tonic-gate 				    (u_offset_t)lh->lh_maxbsize;
17980Sstevel@tonic-gate 			}
17990Sstevel@tonic-gate 
18000Sstevel@tonic-gate 			/*
18010Sstevel@tonic-gate 			 * Add in the size-growth of the attrcache.
18020Sstevel@tonic-gate 			 * len will be non-zero only for the record type
18030Sstevel@tonic-gate 			 * CACHEFS_LOG_MDCREATE, and len can't be > 2GB because
18040Sstevel@tonic-gate 			 * it refers to the number of entries in
18050Sstevel@tonic-gate 			 * the attribute cache file.
18060Sstevel@tonic-gate 			 */
18070Sstevel@tonic-gate 			assert(len <= UINT_MAX);
18080Sstevel@tonic-gate 			delta = stats_dbm_attrcache_addsize(st, mip, fileno,
18090Sstevel@tonic-gate 			    (type == CACHEFS_LOG_MDCREATE) ? (uint_t)len : 0);
18100Sstevel@tonic-gate 			st->st_ws_current += (u_offset_t)delta;
18110Sstevel@tonic-gate 			mip->mi_current += (u_offset_t)delta;
18120Sstevel@tonic-gate 
18130Sstevel@tonic-gate 			/* see if this is an `expensive' logfile */
18140Sstevel@tonic-gate 			if ((! st->st_ws_expensive) && (rflags & GRI_EXPENSIVE))
18150Sstevel@tonic-gate 				st->st_ws_expensive = 1;
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 			/* subtract current frontfile size ... */
18180Sstevel@tonic-gate 			st->st_ws_current -= fip->fi_total;
18190Sstevel@tonic-gate 			mip->mi_current -= fip->fi_total;
18200Sstevel@tonic-gate 
18210Sstevel@tonic-gate 			/* compute new frontfile size */
18220Sstevel@tonic-gate 			if ((mip->mi_flags & CFS_WRITE_AROUND) &&
18230Sstevel@tonic-gate 			    (rflags & GRI_MODIFY)) {
18240Sstevel@tonic-gate 				fip->fi_total = 0LL;
18250Sstevel@tonic-gate 				fip->fi_ent_n = 0;
18260Sstevel@tonic-gate 			} else if (rflags & GRI_ADD) {
18270Sstevel@tonic-gate 				stats_log_fi_add(st, fip, off, len);
18280Sstevel@tonic-gate 			} else if (rflags & GRI_TRUNC) {
18290Sstevel@tonic-gate 				stats_log_fi_trunc(st, fip, off, len);
18300Sstevel@tonic-gate 			}
18310Sstevel@tonic-gate 			if (rflags & GRI_METADATA)
18320Sstevel@tonic-gate 				fip->fi_flags |= FI_METADATA;
18330Sstevel@tonic-gate 
18340Sstevel@tonic-gate 			/* add back in new frontfile size */
18350Sstevel@tonic-gate 			mip->mi_current += fip->fi_total;
18360Sstevel@tonic-gate 			if (mip->mi_current > mip->mi_high)
18370Sstevel@tonic-gate 				mip->mi_high = mip->mi_current;
18380Sstevel@tonic-gate 			stats_dbm_store_byvfsp(st, vfsp, mip);
18390Sstevel@tonic-gate 			free(mip);
18400Sstevel@tonic-gate 			st->st_ws_current += fip->fi_total;
18410Sstevel@tonic-gate 			if (st->st_ws_current > st->st_ws_high)
18420Sstevel@tonic-gate 				st->st_ws_high = st->st_ws_current;
18430Sstevel@tonic-gate 
18440Sstevel@tonic-gate 			stats_dbm_store_byfid(st, fidp, fip);
18450Sstevel@tonic-gate 			if (fip != &fi)
18460Sstevel@tonic-gate 				free(fip);
18470Sstevel@tonic-gate 			break;
18480Sstevel@tonic-gate 		}
18490Sstevel@tonic-gate 
18500Sstevel@tonic-gate 		free(record);
18510Sstevel@tonic-gate 
18520Sstevel@tonic-gate 		if (stats_inerror(st))
18530Sstevel@tonic-gate 			break;
18540Sstevel@tonic-gate 	}
18550Sstevel@tonic-gate 
18560Sstevel@tonic-gate out:
18570Sstevel@tonic-gate 	if (mi != NULL)
18580Sstevel@tonic-gate 		free(mi);
18590Sstevel@tonic-gate 	if (! stats_inerror(st))
18600Sstevel@tonic-gate 		st->st_flags |= ST_WSCOMP;
18610Sstevel@tonic-gate }
18620Sstevel@tonic-gate 
18630Sstevel@tonic-gate int
stats_log_wssize_init(stats_cookie_t * st)18640Sstevel@tonic-gate stats_log_wssize_init(stats_cookie_t *st)
18650Sstevel@tonic-gate {
18660Sstevel@tonic-gate 	assert(stats_good(st));
18670Sstevel@tonic-gate 	assert(st->st_flags & ST_WSCOMP);
18680Sstevel@tonic-gate 
18690Sstevel@tonic-gate 	return (st->st_ws_init);
18700Sstevel@tonic-gate }
18710Sstevel@tonic-gate 
18720Sstevel@tonic-gate u_offset_t
stats_log_wssize_current(stats_cookie_t * st)18730Sstevel@tonic-gate stats_log_wssize_current(stats_cookie_t *st)
18740Sstevel@tonic-gate {
18750Sstevel@tonic-gate 	assert(stats_good(st));
18760Sstevel@tonic-gate 	assert(st->st_flags & ST_WSCOMP);
18770Sstevel@tonic-gate 
18780Sstevel@tonic-gate 	return (st->st_ws_current);
18790Sstevel@tonic-gate }
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate u_offset_t
stats_log_wssize_high(stats_cookie_t * st)18820Sstevel@tonic-gate stats_log_wssize_high(stats_cookie_t *st)
18830Sstevel@tonic-gate {
18840Sstevel@tonic-gate 	assert(stats_good(st));
18850Sstevel@tonic-gate 	assert(st->st_flags & ST_WSCOMP);
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 	return (st->st_ws_high);
18880Sstevel@tonic-gate }
18890Sstevel@tonic-gate 
18900Sstevel@tonic-gate 
18910Sstevel@tonic-gate int
stats_log_wssize_expensive(stats_cookie_t * st)18920Sstevel@tonic-gate stats_log_wssize_expensive(stats_cookie_t *st)
18930Sstevel@tonic-gate {
18940Sstevel@tonic-gate 	assert(stats_good(st));
18950Sstevel@tonic-gate 	assert(st->st_flags & ST_WSCOMP);
18960Sstevel@tonic-gate 
18970Sstevel@tonic-gate 	return (st->st_ws_expensive);
18980Sstevel@tonic-gate }
1899