xref: /onnv-gate/usr/src/cmd/fs.d/cachefs/cfsd/cfsd_logfile.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1994-2002 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * Methods of the cfsd_maptbl classes.
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #include <stdio.h>
34*0Sstevel@tonic-gate #include <stdlib.h>
35*0Sstevel@tonic-gate #include <stddef.h>
36*0Sstevel@tonic-gate #include <string.h>
37*0Sstevel@tonic-gate #include <synch.h>
38*0Sstevel@tonic-gate #include <unistd.h>
39*0Sstevel@tonic-gate #include <fcntl.h>
40*0Sstevel@tonic-gate #include <errno.h>
41*0Sstevel@tonic-gate #include <sys/utsname.h>
42*0Sstevel@tonic-gate #include <sys/vfs.h>
43*0Sstevel@tonic-gate #include <sys/cred.h>
44*0Sstevel@tonic-gate #include <sys/param.h>
45*0Sstevel@tonic-gate #include <sys/types.h>
46*0Sstevel@tonic-gate #include <sys/stat.h>
47*0Sstevel@tonic-gate #include <sys/mman.h>
48*0Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
49*0Sstevel@tonic-gate #include <sys/fs/cachefs_dlog.h>
50*0Sstevel@tonic-gate #include <mdbug/mdbug.h>
51*0Sstevel@tonic-gate #include "cfsd.h"
52*0Sstevel@tonic-gate #include "cfsd_logfile.h"
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /*
55*0Sstevel@tonic-gate  *			cfsd_logfile_create
56*0Sstevel@tonic-gate  *
57*0Sstevel@tonic-gate  * Description:
58*0Sstevel@tonic-gate  * Arguments:
59*0Sstevel@tonic-gate  * Returns:
60*0Sstevel@tonic-gate  * Preconditions:
61*0Sstevel@tonic-gate  */
62*0Sstevel@tonic-gate cfsd_logfile_object_t *
cfsd_logfile_create(void)63*0Sstevel@tonic-gate cfsd_logfile_create(void)
64*0Sstevel@tonic-gate {
65*0Sstevel@tonic-gate 	cfsd_logfile_object_t *logfile_object_p;
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate 	dbug_enter("cfsd_logfile_create");
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	logfile_object_p = cfsd_calloc(sizeof (cfsd_logfile_object_t));
70*0Sstevel@tonic-gate 	logfile_object_p->i_fid = -1;
71*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_pa = NULL;
72*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_paoff = 0;
73*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_paend = 0;
74*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_palen = 0;
75*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_pa = NULL;
76*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_paoff = 0;
77*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_paend = 0;
78*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_palen = 0;
79*0Sstevel@tonic-gate 	logfile_object_p->i_cur_offset = 0;
80*0Sstevel@tonic-gate 	logfile_object_p->i_cur_entry = NULL;
81*0Sstevel@tonic-gate 	dbug_leave("cfsd_logfile_create");
82*0Sstevel@tonic-gate 	return (logfile_object_p);
83*0Sstevel@tonic-gate }
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate /*
86*0Sstevel@tonic-gate  *			cfsd_logfile_destroy
87*0Sstevel@tonic-gate  *
88*0Sstevel@tonic-gate  * Description:
89*0Sstevel@tonic-gate  * Arguments:
90*0Sstevel@tonic-gate  * Returns:
91*0Sstevel@tonic-gate  * Preconditions:
92*0Sstevel@tonic-gate  */
93*0Sstevel@tonic-gate void
cfsd_logfile_destroy(cfsd_logfile_object_t * logfile_object_p)94*0Sstevel@tonic-gate cfsd_logfile_destroy(cfsd_logfile_object_t *logfile_object_p)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate 	dbug_enter("cfsd_logfile_destroy");
97*0Sstevel@tonic-gate 	logfile_sync(logfile_object_p);
98*0Sstevel@tonic-gate 	logfile_teardown(logfile_object_p);
99*0Sstevel@tonic-gate 	cfsd_free(logfile_object_p);
100*0Sstevel@tonic-gate 	dbug_leave("cfsd_logfile_destroy");
101*0Sstevel@tonic-gate }
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate /*
104*0Sstevel@tonic-gate  *			logfile_domap
105*0Sstevel@tonic-gate  *
106*0Sstevel@tonic-gate  * Description:
107*0Sstevel@tonic-gate  *	Maps in the specified section of the file.
108*0Sstevel@tonic-gate  * Arguments:
109*0Sstevel@tonic-gate  *	off	The offset to map in.  Must be i_pagesize aligned.
110*0Sstevel@tonic-gate  *	map	0 means use map_entry, 1 means use map_offset
111*0Sstevel@tonic-gate  * Returns:
112*0Sstevel@tonic-gate  *	Returns 0 for success or an errno value on failure.
113*0Sstevel@tonic-gate  * Preconditions:
114*0Sstevel@tonic-gate  */
115*0Sstevel@tonic-gate int
logfile_domap(cfsd_logfile_object_t * logfile_object_p,off_t off,int map)116*0Sstevel@tonic-gate logfile_domap(cfsd_logfile_object_t *logfile_object_p, off_t off, int map)
117*0Sstevel@tonic-gate {
118*0Sstevel@tonic-gate 	int xx;
119*0Sstevel@tonic-gate 	int len;
120*0Sstevel@tonic-gate 	mmap_info_t *mmp;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	dbug_enter("logfile_domap");
123*0Sstevel@tonic-gate 	dbug_precond(logfile_object_p->i_fid >= 0);
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 	len = logfile_object_p->i_maplen;
126*0Sstevel@tonic-gate 	mmp = (map == 0) ?
127*0Sstevel@tonic-gate 		&logfile_object_p->i_map_entry :
128*0Sstevel@tonic-gate 		&logfile_object_p->i_map_offset;
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	logfile_object_p->i_stat_mapmove++;
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	/* destroy old mapping if it exists */
133*0Sstevel@tonic-gate 	if (mmp->i_pa) {
134*0Sstevel@tonic-gate 		/* determine how far we have to move the map */
135*0Sstevel@tonic-gate 		logfile_object_p->i_stat_mapdist += abs(mmp->i_paoff - off);
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 		/* remove the map */
138*0Sstevel@tonic-gate 		xx = munmap(mmp->i_pa, mmp->i_palen);
139*0Sstevel@tonic-gate 		if (xx == -1) {
140*0Sstevel@tonic-gate 			xx = errno;
141*0Sstevel@tonic-gate 			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
142*0Sstevel@tonic-gate 			    logfile_object_p->i_name, xx, mmp->i_pa,
143*0Sstevel@tonic-gate 			    mmp->i_palen));
144*0Sstevel@tonic-gate 		}
145*0Sstevel@tonic-gate 		mmp->i_pa = NULL;
146*0Sstevel@tonic-gate 		mmp->i_palen = 0;
147*0Sstevel@tonic-gate 		mmp->i_paoff = 0;
148*0Sstevel@tonic-gate 		mmp->i_paend = 0;
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	/* do the mapping */
152*0Sstevel@tonic-gate 	mmp->i_pa = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
153*0Sstevel@tonic-gate 	    logfile_object_p->i_fid, off);
154*0Sstevel@tonic-gate 	if (mmp->i_pa == MAP_FAILED) {
155*0Sstevel@tonic-gate 		xx = errno;
156*0Sstevel@tonic-gate 		dbug_print(("error",
157*0Sstevel@tonic-gate 		    "Could not map %s, error %d, off %d, len %d",
158*0Sstevel@tonic-gate 		    logfile_object_p->i_name, xx, off, len));
159*0Sstevel@tonic-gate 		mmp->i_pa = NULL;
160*0Sstevel@tonic-gate 		dbug_leave("logfile_domap");
161*0Sstevel@tonic-gate 		return (xx);
162*0Sstevel@tonic-gate 	}
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	mmp->i_palen = len;
165*0Sstevel@tonic-gate 	mmp->i_paoff = off;
166*0Sstevel@tonic-gate 	mmp->i_paend = off + len - 1;
167*0Sstevel@tonic-gate 	dbug_leave("logfile_domap");
168*0Sstevel@tonic-gate 	return (0);
169*0Sstevel@tonic-gate }
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate /*
172*0Sstevel@tonic-gate  *			logfile_getaddr
173*0Sstevel@tonic-gate  *
174*0Sstevel@tonic-gate  * Description:
175*0Sstevel@tonic-gate  *	Returns an address of a particular offset in the file.
176*0Sstevel@tonic-gate  *	The size of the item to map is i_maxmap
177*0Sstevel@tonic-gate  *	This routine assumes that if we have to remap that i_maxmap
178*0Sstevel@tonic-gate  *	will fit inside the default mapping size.
179*0Sstevel@tonic-gate  * Arguments:
180*0Sstevel@tonic-gate  *	start	offset in the file to map
181*0Sstevel@tonic-gate  *	map	0 means use map_entry, 1 means use map_offset
182*0Sstevel@tonic-gate  * Returns:
183*0Sstevel@tonic-gate  *	Returns NULL for a failure with the mapping file.
184*0Sstevel@tonic-gate  * Preconditions:
185*0Sstevel@tonic-gate  */
186*0Sstevel@tonic-gate caddr_t
logfile_getaddr(cfsd_logfile_object_t * logfile_object_p,off_t start,int map)187*0Sstevel@tonic-gate logfile_getaddr(cfsd_logfile_object_t *logfile_object_p, off_t start, int map)
188*0Sstevel@tonic-gate {
189*0Sstevel@tonic-gate 	mmap_info_t *mmp;
190*0Sstevel@tonic-gate 	caddr_t pa;
191*0Sstevel@tonic-gate 	off_t end;
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	dbug_enter("logfile_getaddr");
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 	mmp = (map == 0) ?
196*0Sstevel@tonic-gate 	    &logfile_object_p->i_map_entry :
197*0Sstevel@tonic-gate 	    &logfile_object_p->i_map_offset;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	/* determine the end of the item */
200*0Sstevel@tonic-gate 	end = start + logfile_object_p->i_maxmap - 1;
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 	/* map the entry in if necessary */
203*0Sstevel@tonic-gate 	if ((start < mmp->i_paoff) || (mmp->i_paend < end)) {
204*0Sstevel@tonic-gate 		if (logfile_domap(logfile_object_p,
205*0Sstevel@tonic-gate 		    start & logfile_object_p->i_pagemask, map)) {
206*0Sstevel@tonic-gate 			dbug_leave("logfile_getaddr");
207*0Sstevel@tonic-gate 			return (NULL);
208*0Sstevel@tonic-gate 		}
209*0Sstevel@tonic-gate 		dbug_assert((mmp->i_paoff <= start) && (end <= mmp->i_paend));
210*0Sstevel@tonic-gate 	}
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	/* make an address and return it */
213*0Sstevel@tonic-gate 	pa = mmp->i_pa + (start - mmp->i_paoff);
214*0Sstevel@tonic-gate 	dbug_leave("logfile_getaddr");
215*0Sstevel@tonic-gate 	return (pa);
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate /*
219*0Sstevel@tonic-gate  *			logfile_setup
220*0Sstevel@tonic-gate  *
221*0Sstevel@tonic-gate  * Description:
222*0Sstevel@tonic-gate  *	Sets up to use the specified file.
223*0Sstevel@tonic-gate  *	Call this routine before using any of the other routines.
224*0Sstevel@tonic-gate  * Arguments:
225*0Sstevel@tonic-gate  *	filename	file to use
226*0Sstevel@tonic-gate  *	maxmap		max amount needed after a map
227*0Sstevel@tonic-gate  * Returns:
228*0Sstevel@tonic-gate  *	Returns 0 for success or an errno value.
229*0Sstevel@tonic-gate  * Preconditions:
230*0Sstevel@tonic-gate  *	precond(filename)
231*0Sstevel@tonic-gate  */
232*0Sstevel@tonic-gate int
logfile_setup(cfsd_logfile_object_t * logfile_object_p,const char * filename,int maxmap)233*0Sstevel@tonic-gate logfile_setup(cfsd_logfile_object_t *logfile_object_p,
234*0Sstevel@tonic-gate 	const char *filename, int maxmap)
235*0Sstevel@tonic-gate {
236*0Sstevel@tonic-gate 	int xx;
237*0Sstevel@tonic-gate 	struct stat sinfo;
238*0Sstevel@tonic-gate 	long *versionp;
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 	dbug_enter("logfile_setup");
241*0Sstevel@tonic-gate 	dbug_precond(filename);
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	/* clean up from a previous setup */
244*0Sstevel@tonic-gate 	logfile_teardown(logfile_object_p);
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	strlcpy(logfile_object_p->i_name, filename,
247*0Sstevel@tonic-gate 	    sizeof (logfile_object_p->i_name));
248*0Sstevel@tonic-gate 	dbug_print(("info", "filename %s", logfile_object_p->i_name));
249*0Sstevel@tonic-gate 	logfile_object_p->i_maxmap = maxmap;
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	/* get the page info */
252*0Sstevel@tonic-gate 	logfile_object_p->i_pagesize = PAGESIZE;
253*0Sstevel@tonic-gate 	logfile_object_p->i_pagemask = PAGEMASK;
254*0Sstevel@tonic-gate 	logfile_object_p->i_maplen = logfile_object_p->i_pagesize * 100;
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	/* open the file */
257*0Sstevel@tonic-gate 	logfile_object_p->i_fid = open(logfile_object_p->i_name,
258*0Sstevel@tonic-gate 	    O_RDWR | O_NONBLOCK);
259*0Sstevel@tonic-gate 	if (logfile_object_p->i_fid == -1) {
260*0Sstevel@tonic-gate 		xx = errno;
261*0Sstevel@tonic-gate 		dbug_print(("error", "Could not open %s, %d",
262*0Sstevel@tonic-gate 		    logfile_object_p->i_name, xx));
263*0Sstevel@tonic-gate 		dbug_leave("logfile_setup");
264*0Sstevel@tonic-gate 		return (xx);
265*0Sstevel@tonic-gate 	}
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate 	/* get the size and type of file */
268*0Sstevel@tonic-gate 	xx = fstat(logfile_object_p->i_fid, &sinfo);
269*0Sstevel@tonic-gate 	if (xx) {
270*0Sstevel@tonic-gate 		xx = errno;
271*0Sstevel@tonic-gate 		if (xx == ENOENT) {
272*0Sstevel@tonic-gate 			dbug_print(("info", "No log file to roll"));
273*0Sstevel@tonic-gate 		} else {
274*0Sstevel@tonic-gate 			dbug_print(("error", "Could not stat %s, %d",
275*0Sstevel@tonic-gate 			    logfile_object_p->i_name, xx));
276*0Sstevel@tonic-gate 		}
277*0Sstevel@tonic-gate 		dbug_leave("logfile_setup");
278*0Sstevel@tonic-gate 		return (xx);
279*0Sstevel@tonic-gate 	}
280*0Sstevel@tonic-gate 	logfile_object_p->i_size = sinfo.st_size;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	/* sanity check, better be a regular file */
283*0Sstevel@tonic-gate 	if (!S_ISREG(sinfo.st_mode)) {
284*0Sstevel@tonic-gate 		xx = ENOTSUP;
285*0Sstevel@tonic-gate 		dbug_print(("error", "%s Not a regular file.",
286*0Sstevel@tonic-gate 		    logfile_object_p->i_name));
287*0Sstevel@tonic-gate 		dbug_leave("logfile_setup");
288*0Sstevel@tonic-gate 		return (xx);
289*0Sstevel@tonic-gate 	}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 	/* better not be too small */
292*0Sstevel@tonic-gate 	if (logfile_object_p->i_size < LOGFILE_ENTRY_START) {
293*0Sstevel@tonic-gate 		dbug_print(("error", "File %s is too small %d.",
294*0Sstevel@tonic-gate 		    logfile_object_p->i_name, logfile_object_p->i_size));
295*0Sstevel@tonic-gate 		dbug_leave("logfile_setup");
296*0Sstevel@tonic-gate 		return (EINVAL);
297*0Sstevel@tonic-gate 	}
298*0Sstevel@tonic-gate 
299*0Sstevel@tonic-gate 	/* initialize statistic gathering */
300*0Sstevel@tonic-gate 	logfile_object_p->i_stat_mapmove = 0;
301*0Sstevel@tonic-gate 	logfile_object_p->i_stat_mapdist = 0;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	/* check the version number */
304*0Sstevel@tonic-gate 	versionp = (long *)logfile_getaddr(logfile_object_p, 0, 1);
305*0Sstevel@tonic-gate 	if (versionp == NULL) {
306*0Sstevel@tonic-gate 		dbug_leave("logfile_setup");
307*0Sstevel@tonic-gate 		return (EIO);
308*0Sstevel@tonic-gate 	}
309*0Sstevel@tonic-gate 	if (*versionp != CFS_DLOG_VERSION) {
310*0Sstevel@tonic-gate 		dbug_print(("error", "Log file version mismatch %d != %d",
311*0Sstevel@tonic-gate 		    *versionp, CFS_DLOG_VERSION));
312*0Sstevel@tonic-gate 		dbug_leave("logfile_setup");
313*0Sstevel@tonic-gate 		return (EINVAL);
314*0Sstevel@tonic-gate 	}
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 	/* return success */
317*0Sstevel@tonic-gate 	dbug_leave("logfile_setup");
318*0Sstevel@tonic-gate 	return (0);
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate /*
322*0Sstevel@tonic-gate  *			logfile_teardown
323*0Sstevel@tonic-gate  *
324*0Sstevel@tonic-gate  * Description:
325*0Sstevel@tonic-gate  *	Uninitializes the object.
326*0Sstevel@tonic-gate  *	Call logfile_setup before using this object again.
327*0Sstevel@tonic-gate  * Arguments:
328*0Sstevel@tonic-gate  * Returns:
329*0Sstevel@tonic-gate  * Preconditions:
330*0Sstevel@tonic-gate  */
331*0Sstevel@tonic-gate void
logfile_teardown(cfsd_logfile_object_t * logfile_object_p)332*0Sstevel@tonic-gate logfile_teardown(cfsd_logfile_object_t *logfile_object_p)
333*0Sstevel@tonic-gate {
334*0Sstevel@tonic-gate 	int xx;
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 	dbug_enter("logfile_teardown");
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	if (logfile_object_p->i_map_entry.i_pa) {
339*0Sstevel@tonic-gate 		xx = munmap(logfile_object_p->i_map_entry.i_pa,
340*0Sstevel@tonic-gate 		    logfile_object_p->i_map_entry.i_palen);
341*0Sstevel@tonic-gate 		if (xx == -1) {
342*0Sstevel@tonic-gate 			xx = errno;
343*0Sstevel@tonic-gate 			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
344*0Sstevel@tonic-gate 			    logfile_object_p->i_name, xx,
345*0Sstevel@tonic-gate 			    logfile_object_p->i_map_entry.i_pa,
346*0Sstevel@tonic-gate 			    logfile_object_p->i_map_entry.i_palen));
347*0Sstevel@tonic-gate 		}
348*0Sstevel@tonic-gate 		logfile_object_p->i_map_entry.i_pa = NULL;
349*0Sstevel@tonic-gate 	}
350*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_paoff = 0;
351*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_paend = 0;
352*0Sstevel@tonic-gate 	logfile_object_p->i_map_entry.i_palen = 0;
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate 	if (logfile_object_p->i_map_offset.i_pa) {
355*0Sstevel@tonic-gate 		xx = munmap(logfile_object_p->i_map_offset.i_pa,
356*0Sstevel@tonic-gate 		    logfile_object_p->i_map_offset.i_palen);
357*0Sstevel@tonic-gate 		if (xx == -1) {
358*0Sstevel@tonic-gate 			xx = errno;
359*0Sstevel@tonic-gate 			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
360*0Sstevel@tonic-gate 			    logfile_object_p->i_name, xx,
361*0Sstevel@tonic-gate 			    logfile_object_p->i_map_offset.i_pa,
362*0Sstevel@tonic-gate 			    logfile_object_p->i_map_offset.i_palen));
363*0Sstevel@tonic-gate 		}
364*0Sstevel@tonic-gate 		logfile_object_p->i_map_offset.i_pa = NULL;
365*0Sstevel@tonic-gate 	}
366*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_paoff = 0;
367*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_paend = 0;
368*0Sstevel@tonic-gate 	logfile_object_p->i_map_offset.i_palen = 0;
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	if (logfile_object_p->i_fid != -1) {
371*0Sstevel@tonic-gate 		if (close(logfile_object_p->i_fid))
372*0Sstevel@tonic-gate 			dbug_print(("error", "Could not close %s, %d",
373*0Sstevel@tonic-gate 			    logfile_object_p->i_name, errno));
374*0Sstevel@tonic-gate 		logfile_object_p->i_fid = -1;
375*0Sstevel@tonic-gate 	}
376*0Sstevel@tonic-gate 	logfile_object_p->i_cur_offset = 0;
377*0Sstevel@tonic-gate 	logfile_object_p->i_cur_entry = NULL;
378*0Sstevel@tonic-gate 	dbug_leave("logfile_teardown");
379*0Sstevel@tonic-gate }
380*0Sstevel@tonic-gate 
381*0Sstevel@tonic-gate /*
382*0Sstevel@tonic-gate  *			logfile_entry
383*0Sstevel@tonic-gate  *
384*0Sstevel@tonic-gate  * Description:
385*0Sstevel@tonic-gate  *	Sets addrp to the address of the log entry at offset
386*0Sstevel@tonic-gate  *	The mapping remains in effect until:
387*0Sstevel@tonic-gate  *		a) this routine is called again
388*0Sstevel@tonic-gate  *		b) logfile_teardown is called
389*0Sstevel@tonic-gate  *		c) this object is destroyed
390*0Sstevel@tonic-gate  * Arguments:
391*0Sstevel@tonic-gate  *	offset	offset to start of entry
392*0Sstevel@tonic-gate  *	entpp	place to store address
393*0Sstevel@tonic-gate  * Returns:
394*0Sstevel@tonic-gate  *	Returns 0 for success, 1 for EOF, -1 if a fatal error occurs.
395*0Sstevel@tonic-gate  * Preconditions:
396*0Sstevel@tonic-gate  *	precond(addrp)
397*0Sstevel@tonic-gate  */
398*0Sstevel@tonic-gate int
logfile_entry(cfsd_logfile_object_t * logfile_object_p,off_t offset,cfs_dlog_entry_t ** entpp)399*0Sstevel@tonic-gate logfile_entry(cfsd_logfile_object_t *logfile_object_p,
400*0Sstevel@tonic-gate 	off_t offset,
401*0Sstevel@tonic-gate 	cfs_dlog_entry_t **entpp)
402*0Sstevel@tonic-gate {
403*0Sstevel@tonic-gate 	cfs_dlog_entry_t *entp;
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 	dbug_enter("logfile_entry");
406*0Sstevel@tonic-gate 	dbug_precond(entpp);
407*0Sstevel@tonic-gate 	dbug_precond(offset >= sizeof (long));
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	logfile_object_p->i_stat_nextcnt++;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	/* check for eof */
413*0Sstevel@tonic-gate 	if (offset >= logfile_object_p->i_size) {
414*0Sstevel@tonic-gate 		dbug_leave("logfile_entry");
415*0Sstevel@tonic-gate 		return (1);
416*0Sstevel@tonic-gate 	}
417*0Sstevel@tonic-gate 	dbug_assert((offset & 3) == 0);
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 	/* get the address of the entry */
420*0Sstevel@tonic-gate 	entp = (cfs_dlog_entry_t *)logfile_getaddr(logfile_object_p, offset, 0);
421*0Sstevel@tonic-gate 	if (entp == NULL) {
422*0Sstevel@tonic-gate 		dbug_leave("logfile_entry");
423*0Sstevel@tonic-gate 		return (-1);
424*0Sstevel@tonic-gate 	}
425*0Sstevel@tonic-gate 	/* sanity check, record should be alligned */
426*0Sstevel@tonic-gate 	if (entp->dl_len & 3) {
427*0Sstevel@tonic-gate 		dbug_print(("error",
428*0Sstevel@tonic-gate 		    "Record at offset %d length is not alligned %d",
429*0Sstevel@tonic-gate 		    offset, entp->dl_len));
430*0Sstevel@tonic-gate 		dbug_leave("logfile_entry");
431*0Sstevel@tonic-gate 		return (-1);
432*0Sstevel@tonic-gate 	}
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate 	/* sanity check record should a reasonable size */
435*0Sstevel@tonic-gate 	if ((entp->dl_len < CFS_DLOG_ENTRY_MINSIZE) ||
436*0Sstevel@tonic-gate 	    (entp->dl_len > CFS_DLOG_ENTRY_MAXSIZE)) {
437*0Sstevel@tonic-gate 		dbug_print(("error",
438*0Sstevel@tonic-gate 		    "Record at offset %d has an invalid size %d", offset,
439*0Sstevel@tonic-gate 		    entp->dl_len));
440*0Sstevel@tonic-gate 		dbug_leave("logfile_entry");
441*0Sstevel@tonic-gate 		return (-1);
442*0Sstevel@tonic-gate 	}
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 	/* preserve offset and pointer */
445*0Sstevel@tonic-gate 	logfile_object_p->i_cur_offset = offset;
446*0Sstevel@tonic-gate 	logfile_object_p->i_cur_entry = entp;
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	/* return success */
449*0Sstevel@tonic-gate 	*entpp = entp;
450*0Sstevel@tonic-gate 	dbug_leave("logfile_entry");
451*0Sstevel@tonic-gate 	return (0);
452*0Sstevel@tonic-gate }
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate /*
455*0Sstevel@tonic-gate  *			logfile_offset
456*0Sstevel@tonic-gate  *
457*0Sstevel@tonic-gate  * Description:
458*0Sstevel@tonic-gate  *	Sets addrp to the address of the specified offset.
459*0Sstevel@tonic-gate  *	The mapping remains in effect until:
460*0Sstevel@tonic-gate  *		a) this routine is called again
461*0Sstevel@tonic-gate  *		b) logfile_teardown is called
462*0Sstevel@tonic-gate  *		c) this object is destroyed
463*0Sstevel@tonic-gate  * Arguments:
464*0Sstevel@tonic-gate  *	offset	offset into file, must be 0 <= offset < i_size
465*0Sstevel@tonic-gate  *	addrp	returns mapped address
466*0Sstevel@tonic-gate  * Returns:
467*0Sstevel@tonic-gate  *	Returns 0 for success, -1 if a fatal error occurs.
468*0Sstevel@tonic-gate  * Preconditions:
469*0Sstevel@tonic-gate  *	precond(addrp)
470*0Sstevel@tonic-gate  */
471*0Sstevel@tonic-gate int
logfile_offset(cfsd_logfile_object_t * logfile_object_p,off_t offset,caddr_t * addrp)472*0Sstevel@tonic-gate logfile_offset(cfsd_logfile_object_t *logfile_object_p,
473*0Sstevel@tonic-gate 	off_t offset,
474*0Sstevel@tonic-gate 	caddr_t *addrp)
475*0Sstevel@tonic-gate {
476*0Sstevel@tonic-gate 	caddr_t pa;
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 	dbug_enter("logfile_offset");
479*0Sstevel@tonic-gate 	dbug_precond(addrp);
480*0Sstevel@tonic-gate 	dbug_precond((0 <= offset) && (offset < logfile_object_p->i_size));
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate 	logfile_object_p->i_stat_offcnt++;
483*0Sstevel@tonic-gate 
484*0Sstevel@tonic-gate 	/* get the address for the offset */
485*0Sstevel@tonic-gate 	pa = logfile_getaddr(logfile_object_p, offset, 1);
486*0Sstevel@tonic-gate 	if (pa == NULL) {
487*0Sstevel@tonic-gate 		dbug_leave("logfile_offset");
488*0Sstevel@tonic-gate 		return (-1);
489*0Sstevel@tonic-gate 	}
490*0Sstevel@tonic-gate 	/* return success */
491*0Sstevel@tonic-gate 	*addrp = pa;
492*0Sstevel@tonic-gate 	dbug_leave("logfile_offset");
493*0Sstevel@tonic-gate 	return (0);
494*0Sstevel@tonic-gate }
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate /*
497*0Sstevel@tonic-gate  *			logfile_sync
498*0Sstevel@tonic-gate  *
499*0Sstevel@tonic-gate  * Description:
500*0Sstevel@tonic-gate  *	Performs an fsync on the log file.
501*0Sstevel@tonic-gate  * Arguments:
502*0Sstevel@tonic-gate  * Returns:
503*0Sstevel@tonic-gate  *	Returns 0 for success or an errno value on failure.
504*0Sstevel@tonic-gate  * Preconditions:
505*0Sstevel@tonic-gate  */
506*0Sstevel@tonic-gate int
logfile_sync(cfsd_logfile_object_t * logfile_object_p)507*0Sstevel@tonic-gate logfile_sync(cfsd_logfile_object_t *logfile_object_p)
508*0Sstevel@tonic-gate {
509*0Sstevel@tonic-gate 	int xx;
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 	dbug_enter("logfile_sync");
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 	if (logfile_object_p->i_fid == -1) {
514*0Sstevel@tonic-gate 		dbug_leave("logfile_sync");
515*0Sstevel@tonic-gate 		return (0);
516*0Sstevel@tonic-gate 	}
517*0Sstevel@tonic-gate 	xx = fsync(logfile_object_p->i_fid);
518*0Sstevel@tonic-gate 	if (xx) {
519*0Sstevel@tonic-gate 		xx = errno;
520*0Sstevel@tonic-gate 		dbug_print(("error", "fsync failed %d", xx));
521*0Sstevel@tonic-gate 	}
522*0Sstevel@tonic-gate 	dbug_leave("logfile_sync");
523*0Sstevel@tonic-gate 	return (xx);
524*0Sstevel@tonic-gate }
525*0Sstevel@tonic-gate 
526*0Sstevel@tonic-gate /*
527*0Sstevel@tonic-gate  *			logfile_dumpstats
528*0Sstevel@tonic-gate  *
529*0Sstevel@tonic-gate  * Description:
530*0Sstevel@tonic-gate  *	Prints out various stats about the hashing.
531*0Sstevel@tonic-gate  * Arguments:
532*0Sstevel@tonic-gate  * Returns:
533*0Sstevel@tonic-gate  * Preconditions:
534*0Sstevel@tonic-gate  */
535*0Sstevel@tonic-gate void
logfile_dumpstats(cfsd_logfile_object_t * logfile_object_p)536*0Sstevel@tonic-gate logfile_dumpstats(cfsd_logfile_object_t *logfile_object_p)
537*0Sstevel@tonic-gate {
538*0Sstevel@tonic-gate 	int xx;
539*0Sstevel@tonic-gate 	double dd;
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	dbug_enter("logfile_dumpstats");
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 	dbug_print(("dump", "Request - next %d",
544*0Sstevel@tonic-gate 	    logfile_object_p->i_stat_nextcnt));
545*0Sstevel@tonic-gate 	dbug_print(("dump", "Request - offset %d",
546*0Sstevel@tonic-gate 	    logfile_object_p->i_stat_offcnt));
547*0Sstevel@tonic-gate 	dbug_print(("dump", "Map Moves %d", logfile_object_p->i_stat_mapmove));
548*0Sstevel@tonic-gate 	dbug_print(("dump", "Mapping Size %d", logfile_object_p->i_maplen));
549*0Sstevel@tonic-gate 	dbug_print(("dump", "Item Size %d", logfile_object_p->i_maxmap));
550*0Sstevel@tonic-gate 	dbug_print(("dump", "File Size %d", logfile_object_p->i_size));
551*0Sstevel@tonic-gate 	if (logfile_object_p->i_stat_mapmove == 0) {
552*0Sstevel@tonic-gate 		dbug_leave("logfile_dumpstats");
553*0Sstevel@tonic-gate 		return;
554*0Sstevel@tonic-gate 	}
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate 	dd = (double)logfile_object_p->i_stat_mapmove /
557*0Sstevel@tonic-gate 	    (logfile_object_p->i_stat_nextcnt +
558*0Sstevel@tonic-gate 	    logfile_object_p->i_stat_offcnt);
559*0Sstevel@tonic-gate 	dbug_print(("dump", "Mmap moves per Request %.2f", dd));
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 	xx = logfile_object_p->i_stat_mapdist /
562*0Sstevel@tonic-gate 	    logfile_object_p->i_stat_mapmove;
563*0Sstevel@tonic-gate 	dbug_print(("dump", "Average distance per mmap moves %d", xx));
564*0Sstevel@tonic-gate 	dbug_leave("logfile_dumpstats");
565*0Sstevel@tonic-gate }
566