xref: /onnv-gate/usr/src/cmd/fs.d/cachefs/cfsd/cfsd_maptbl.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_maptbl.h"
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /*
55*0Sstevel@tonic-gate  *			cfsd_maptbl_create
56*0Sstevel@tonic-gate  *
57*0Sstevel@tonic-gate  * Description:
58*0Sstevel@tonic-gate  *	Constructor for the cfsd_maptbl class.
59*0Sstevel@tonic-gate  *	Just does some setup not much else.
60*0Sstevel@tonic-gate  * Arguments:
61*0Sstevel@tonic-gate  * Returns:
62*0Sstevel@tonic-gate  * Preconditions:
63*0Sstevel@tonic-gate  */
64*0Sstevel@tonic-gate cfsd_maptbl_object_t *
cfsd_maptbl_create(void)65*0Sstevel@tonic-gate cfsd_maptbl_create(void)
66*0Sstevel@tonic-gate {
67*0Sstevel@tonic-gate 	cfsd_maptbl_object_t *maptbl_object_p;
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	dbug_enter("cfsd_maptbl_create");
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	maptbl_object_p = cfsd_calloc(sizeof (cfsd_maptbl_object_t));
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	maptbl_object_p->i_fid = -1;
74*0Sstevel@tonic-gate 	maptbl_object_p->i_pa = NULL;
75*0Sstevel@tonic-gate 	maptbl_object_p->i_paoff = 0;
76*0Sstevel@tonic-gate 	maptbl_object_p->i_paend = 0;
77*0Sstevel@tonic-gate 	maptbl_object_p->i_palen = 0;
78*0Sstevel@tonic-gate 	dbug_leave("cfsd_maptbl_create");
79*0Sstevel@tonic-gate 	return (maptbl_object_p);
80*0Sstevel@tonic-gate }
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate /*
83*0Sstevel@tonic-gate  *			cfsd_maptbl_destroy
84*0Sstevel@tonic-gate  *
85*0Sstevel@tonic-gate  * Description:
86*0Sstevel@tonic-gate  *	Destructor for the cfsd_maptbl class.
87*0Sstevel@tonic-gate  * Arguments:
88*0Sstevel@tonic-gate  * Returns:
89*0Sstevel@tonic-gate  * Preconditions:
90*0Sstevel@tonic-gate  */
91*0Sstevel@tonic-gate void
cfsd_maptbl_destroy(cfsd_maptbl_object_t * maptbl_object_p)92*0Sstevel@tonic-gate cfsd_maptbl_destroy(cfsd_maptbl_object_t *maptbl_object_p)
93*0Sstevel@tonic-gate {
94*0Sstevel@tonic-gate 	dbug_enter("cfsd_maptbl_destroy");
95*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
96*0Sstevel@tonic-gate 	maptbl_teardown(maptbl_object_p);
97*0Sstevel@tonic-gate 	cfsd_free(maptbl_object_p);
98*0Sstevel@tonic-gate 	dbug_leave("cfsd_maptbl_destroy");
99*0Sstevel@tonic-gate }
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate /*
102*0Sstevel@tonic-gate  *			maptbl_domap
103*0Sstevel@tonic-gate  *
104*0Sstevel@tonic-gate  * Description:
105*0Sstevel@tonic-gate  *	Maps in the specified section of the file.
106*0Sstevel@tonic-gate  * Arguments:
107*0Sstevel@tonic-gate  *	off	The offset to map in.  Must be i_pagesize aligned.
108*0Sstevel@tonic-gate  * Returns:
109*0Sstevel@tonic-gate  *	Returns 0 for success or an errno value on failure.
110*0Sstevel@tonic-gate  * Preconditions:
111*0Sstevel@tonic-gate  */
112*0Sstevel@tonic-gate int
maptbl_domap(cfsd_maptbl_object_t * maptbl_object_p,off_t off)113*0Sstevel@tonic-gate maptbl_domap(cfsd_maptbl_object_t *maptbl_object_p, off_t off)
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate 	int xx;
116*0Sstevel@tonic-gate 	int len;
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	dbug_enter("maptbl_domap");
119*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
120*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p->i_fid >= 0);
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	len = maptbl_object_p->i_maplen;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_mapmove++;
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	/* destroy old mapping if it exists */
127*0Sstevel@tonic-gate 	if (maptbl_object_p->i_pa) {
128*0Sstevel@tonic-gate 		/* determine how far we have to move the map */
129*0Sstevel@tonic-gate 		maptbl_object_p->i_stat_mapdist +=
130*0Sstevel@tonic-gate 		    abs(maptbl_object_p->i_paoff - off);
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 		/* remove the map */
133*0Sstevel@tonic-gate 		xx = munmap(maptbl_object_p->i_pa, maptbl_object_p->i_palen);
134*0Sstevel@tonic-gate 		if (xx == -1) {
135*0Sstevel@tonic-gate 			xx = errno;
136*0Sstevel@tonic-gate 			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
137*0Sstevel@tonic-gate 			    maptbl_object_p->i_name, xx, maptbl_object_p->i_pa,
138*0Sstevel@tonic-gate 			    maptbl_object_p->i_palen));
139*0Sstevel@tonic-gate 		}
140*0Sstevel@tonic-gate 		maptbl_object_p->i_pa = NULL;
141*0Sstevel@tonic-gate 		maptbl_object_p->i_palen = 0;
142*0Sstevel@tonic-gate 		maptbl_object_p->i_paoff = 0;
143*0Sstevel@tonic-gate 		maptbl_object_p->i_paend = 0;
144*0Sstevel@tonic-gate 	}
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	/* do the mapping */
147*0Sstevel@tonic-gate 	maptbl_object_p->i_pa =
148*0Sstevel@tonic-gate 	    mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,
149*0Sstevel@tonic-gate 	    maptbl_object_p->i_fid, off);
150*0Sstevel@tonic-gate 	if (maptbl_object_p->i_pa == MAP_FAILED) {
151*0Sstevel@tonic-gate 		xx = errno;
152*0Sstevel@tonic-gate 		dbug_print(("error",
153*0Sstevel@tonic-gate 		    "Could not map %s, error %d, off %d, len %d",
154*0Sstevel@tonic-gate 		    maptbl_object_p->i_name, xx, off, len));
155*0Sstevel@tonic-gate 		maptbl_object_p->i_pa = NULL;
156*0Sstevel@tonic-gate 		dbug_leave("maptbl_domap");
157*0Sstevel@tonic-gate 		return (xx);
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	maptbl_object_p->i_palen = len;
161*0Sstevel@tonic-gate 	maptbl_object_p->i_paoff = off;
162*0Sstevel@tonic-gate 	maptbl_object_p->i_paend = off + len - 1;
163*0Sstevel@tonic-gate 	dbug_leave("maptbl_domap");
164*0Sstevel@tonic-gate 	return (0);
165*0Sstevel@tonic-gate }
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate /*
168*0Sstevel@tonic-gate  *			maptbl_getaddr
169*0Sstevel@tonic-gate  *
170*0Sstevel@tonic-gate  * Description:
171*0Sstevel@tonic-gate  *	Returns an address of a particular entry in the file.
172*0Sstevel@tonic-gate  * Arguments:
173*0Sstevel@tonic-gate  *	index
174*0Sstevel@tonic-gate  * Returns:
175*0Sstevel@tonic-gate  *	Returns NULL for a failure with the mapping file.
176*0Sstevel@tonic-gate  * Preconditions:
177*0Sstevel@tonic-gate  */
178*0Sstevel@tonic-gate caddr_t
maptbl_getaddr(cfsd_maptbl_object_t * maptbl_object_p,int index)179*0Sstevel@tonic-gate maptbl_getaddr(cfsd_maptbl_object_t *maptbl_object_p, int index)
180*0Sstevel@tonic-gate {
181*0Sstevel@tonic-gate 	off_t start;
182*0Sstevel@tonic-gate 	off_t end;
183*0Sstevel@tonic-gate 	caddr_t pa;
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	dbug_enter("maptbl_getaddr");
186*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
187*0Sstevel@tonic-gate 	dbug_precond(index < maptbl_object_p->i_entries);
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	/* find the boundaries of the entry */
190*0Sstevel@tonic-gate 	start = index * sizeof (struct cfs_dlog_mapping_space);
191*0Sstevel@tonic-gate 	end = start + sizeof (struct cfs_dlog_mapping_space) - 1;
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	/* map the entry in if necessary */
194*0Sstevel@tonic-gate 	if ((start < maptbl_object_p->i_paoff) ||
195*0Sstevel@tonic-gate 		(maptbl_object_p->i_paend < end)) {
196*0Sstevel@tonic-gate 		if (maptbl_domap(maptbl_object_p,
197*0Sstevel@tonic-gate 		    start & maptbl_object_p->i_pagemask)) {
198*0Sstevel@tonic-gate 			dbug_leave("maptbl_getaddr");
199*0Sstevel@tonic-gate 			return (NULL);
200*0Sstevel@tonic-gate 		}
201*0Sstevel@tonic-gate 	}
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	/* make an address and return it */
204*0Sstevel@tonic-gate 	pa = maptbl_object_p->i_pa + (start - maptbl_object_p->i_paoff);
205*0Sstevel@tonic-gate 	dbug_leave("maptbl_getaddr");
206*0Sstevel@tonic-gate 	return (pa);
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate /*
210*0Sstevel@tonic-gate  *			maptbl_cidhashaddr
211*0Sstevel@tonic-gate  *
212*0Sstevel@tonic-gate  * Description:
213*0Sstevel@tonic-gate  *	Finds the address of the specified cid by hashing to
214*0Sstevel@tonic-gate  *	the appropriate entry.  If the cid does not already
215*0Sstevel@tonic-gate  *	exist in the file, then the address of where it should
216*0Sstevel@tonic-gate  *	reside is returned.
217*0Sstevel@tonic-gate  * Arguments:
218*0Sstevel@tonic-gate  *	cid
219*0Sstevel@tonic-gate  *	addrp
220*0Sstevel@tonic-gate  * Returns:
221*0Sstevel@tonic-gate  *	Returns 0 for success, 1 if entry not found, -1 if an
222*0Sstevel@tonic-gate  *	error occurs in the mapping file.
223*0Sstevel@tonic-gate  * Preconditions:
224*0Sstevel@tonic-gate  */
225*0Sstevel@tonic-gate int
maptbl_cidhashaddr(cfsd_maptbl_object_t * maptbl_object_p,cfs_cid_t cid,caddr_t * addrp)226*0Sstevel@tonic-gate maptbl_cidhashaddr(cfsd_maptbl_object_t *maptbl_object_p,
227*0Sstevel@tonic-gate 	cfs_cid_t cid,
228*0Sstevel@tonic-gate 	caddr_t *addrp)
229*0Sstevel@tonic-gate {
230*0Sstevel@tonic-gate 	ino64_t *pa;
231*0Sstevel@tonic-gate 	int index;
232*0Sstevel@tonic-gate 	ino64_t fileno;
233*0Sstevel@tonic-gate 	int start_index;
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	dbug_enter("maptbl_cidhashaddr");
236*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
237*0Sstevel@tonic-gate 	dbug_precond(addrp);
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_requests++;
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 	/* get the index from the first hash function */
242*0Sstevel@tonic-gate 	index = maptbl_hash1(maptbl_object_p, cid);
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_probes++;
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate 	/* get the address of the entry */
247*0Sstevel@tonic-gate 	pa = (ino64_t *)maptbl_getaddr(maptbl_object_p, index);
248*0Sstevel@tonic-gate 	if (pa == NULL) {
249*0Sstevel@tonic-gate 		dbug_leave("maptbl_cidhashaddr");
250*0Sstevel@tonic-gate 		return (-1);
251*0Sstevel@tonic-gate 	}
252*0Sstevel@tonic-gate 	fileno = *pa;
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	/* check for match */
255*0Sstevel@tonic-gate 	if (fileno == cid.cid_fileno) {
256*0Sstevel@tonic-gate 		*addrp = (caddr_t)pa;
257*0Sstevel@tonic-gate 		dbug_leave("maptbl_cidhashaddr");
258*0Sstevel@tonic-gate 		return (0);
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	/* check for not found */
262*0Sstevel@tonic-gate 	if (fileno == 0) {
263*0Sstevel@tonic-gate 		*addrp = (caddr_t)pa;
264*0Sstevel@tonic-gate 		dbug_leave("maptbl_cidhashaddr");
265*0Sstevel@tonic-gate 		return (1);
266*0Sstevel@tonic-gate 	}
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate 	/* get the index from the second hash function */
269*0Sstevel@tonic-gate 	index = maptbl_hash2(maptbl_object_p, cid, index);
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	/* do a linear search for a match or empty entry */
272*0Sstevel@tonic-gate 	start_index = index;
273*0Sstevel@tonic-gate 	do {
274*0Sstevel@tonic-gate 		maptbl_object_p->i_stat_probes++;
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 		/* get the address of the entry */
277*0Sstevel@tonic-gate 		pa = (ino64_t *)maptbl_getaddr(maptbl_object_p, index);
278*0Sstevel@tonic-gate 		if (pa == NULL) {
279*0Sstevel@tonic-gate 			dbug_leave("maptbl_cidhashaddr");
280*0Sstevel@tonic-gate 			return (-1);
281*0Sstevel@tonic-gate 		}
282*0Sstevel@tonic-gate 		fileno = *pa;
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 		/* check for match */
285*0Sstevel@tonic-gate 		if (fileno == cid.cid_fileno) {
286*0Sstevel@tonic-gate 			*addrp = (caddr_t)pa;
287*0Sstevel@tonic-gate 			dbug_leave("maptbl_cidhashaddr");
288*0Sstevel@tonic-gate 			return (0);
289*0Sstevel@tonic-gate 		}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 		/* check for not found */
292*0Sstevel@tonic-gate 		if (fileno == 0) {
293*0Sstevel@tonic-gate 			*addrp = (caddr_t)pa;
294*0Sstevel@tonic-gate 			dbug_leave("maptbl_cidhashaddr");
295*0Sstevel@tonic-gate 			return (1);
296*0Sstevel@tonic-gate 		}
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 		/* move to the next entry */
299*0Sstevel@tonic-gate 		index++;
300*0Sstevel@tonic-gate 		index = index % maptbl_object_p->i_entries;
301*0Sstevel@tonic-gate 	} while (start_index != index);
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	/* table full, this is bad */
304*0Sstevel@tonic-gate 	dbug_print(("error", "Table is full"));
305*0Sstevel@tonic-gate 	dbug_leave("maptbl_cidhashaddr");
306*0Sstevel@tonic-gate 	return (-1);
307*0Sstevel@tonic-gate }
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate /*
310*0Sstevel@tonic-gate  *			maptbl_hash1
311*0Sstevel@tonic-gate  *
312*0Sstevel@tonic-gate  * Description:
313*0Sstevel@tonic-gate  *	Hashes a cid into an index into the table.
314*0Sstevel@tonic-gate  * Arguments:
315*0Sstevel@tonic-gate  *	cid
316*0Sstevel@tonic-gate  * Returns:
317*0Sstevel@tonic-gate  *	Returns the index.
318*0Sstevel@tonic-gate  * Preconditions:
319*0Sstevel@tonic-gate  */
320*0Sstevel@tonic-gate int
maptbl_hash1(cfsd_maptbl_object_t * maptbl_object_p,cfs_cid_t cid)321*0Sstevel@tonic-gate maptbl_hash1(cfsd_maptbl_object_t *maptbl_object_p, cfs_cid_t cid)
322*0Sstevel@tonic-gate {
323*0Sstevel@tonic-gate 	unsigned int xx;
324*0Sstevel@tonic-gate 	unsigned int a, b;
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
327*0Sstevel@tonic-gate #if 0
328*0Sstevel@tonic-gate 	xx = cid.cid_fileno % i_entries;
329*0Sstevel@tonic-gate #else
330*0Sstevel@tonic-gate 	a = cid.cid_fileno >> 16;
331*0Sstevel@tonic-gate 	b = a ^ cid.cid_fileno;
332*0Sstevel@tonic-gate 	xx = b % maptbl_object_p->i_entries;
333*0Sstevel@tonic-gate #endif
334*0Sstevel@tonic-gate 	return (xx);
335*0Sstevel@tonic-gate }
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate /*
338*0Sstevel@tonic-gate  *			maptbl_hash2
339*0Sstevel@tonic-gate  *
340*0Sstevel@tonic-gate  * Description:
341*0Sstevel@tonic-gate  *	Hashes a cid into an index into the table.
342*0Sstevel@tonic-gate  * Arguments:
343*0Sstevel@tonic-gate  *	cid
344*0Sstevel@tonic-gate  *	index
345*0Sstevel@tonic-gate  * Returns:
346*0Sstevel@tonic-gate  *	Returns the index.
347*0Sstevel@tonic-gate  * Preconditions:
348*0Sstevel@tonic-gate  */
349*0Sstevel@tonic-gate int
maptbl_hash2(cfsd_maptbl_object_t * maptbl_object_p,cfs_cid_t cid,int index)350*0Sstevel@tonic-gate maptbl_hash2(cfsd_maptbl_object_t *maptbl_object_p, cfs_cid_t cid, int index)
351*0Sstevel@tonic-gate {
352*0Sstevel@tonic-gate 	unsigned int xx;
353*0Sstevel@tonic-gate 	unsigned int a, b, c, d;
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
356*0Sstevel@tonic-gate #if 0
357*0Sstevel@tonic-gate 	a = cid.cid_fileno & 0x0ff;
358*0Sstevel@tonic-gate 	b = (cid.cid_fileno >> 8) & 0x0ff;
359*0Sstevel@tonic-gate 	b = cid.cid_fileno ^ a ^ b;
360*0Sstevel@tonic-gate 	xx = b % maptbl_object_p->i_hash2mod;
361*0Sstevel@tonic-gate #else
362*0Sstevel@tonic-gate 	a = cid.cid_fileno & 0x0ff;
363*0Sstevel@tonic-gate 	b = (cid.cid_fileno >> 8) & 0x0ff;
364*0Sstevel@tonic-gate 	c = (cid.cid_fileno >> 16) & 0x0ff;
365*0Sstevel@tonic-gate 	d = (cid.cid_fileno >> 24) & 0x0ff;
366*0Sstevel@tonic-gate 	xx = cid.cid_fileno ^ (a << 8) ^ b ^ c ^ d;
367*0Sstevel@tonic-gate 	xx = xx % maptbl_object_p->i_hash2mod;
368*0Sstevel@tonic-gate #endif
369*0Sstevel@tonic-gate 	xx = (index + xx) % maptbl_object_p->i_entries;
370*0Sstevel@tonic-gate 	return (xx);
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate /*
374*0Sstevel@tonic-gate  *			maptbl_setup
375*0Sstevel@tonic-gate  *
376*0Sstevel@tonic-gate  * Description:
377*0Sstevel@tonic-gate  *	Performs setup for the cfsd_maptbl class.
378*0Sstevel@tonic-gate  *	This routine must be called before other routines are used.
379*0Sstevel@tonic-gate  * Arguments:
380*0Sstevel@tonic-gate  *	filename
381*0Sstevel@tonic-gate  * Returns:
382*0Sstevel@tonic-gate  *	Returns 0 for success or an errno value.
383*0Sstevel@tonic-gate  * Preconditions:
384*0Sstevel@tonic-gate  *	precond(filename)
385*0Sstevel@tonic-gate  */
386*0Sstevel@tonic-gate int
maptbl_setup(cfsd_maptbl_object_t * maptbl_object_p,const char * filename)387*0Sstevel@tonic-gate maptbl_setup(cfsd_maptbl_object_t *maptbl_object_p, const char *filename)
388*0Sstevel@tonic-gate {
389*0Sstevel@tonic-gate 	int xx;
390*0Sstevel@tonic-gate 	struct stat sinfo;
391*0Sstevel@tonic-gate 	off_t offset;
392*0Sstevel@tonic-gate 	long *lp;
393*0Sstevel@tonic-gate 	size_t cnt;
394*0Sstevel@tonic-gate 	off_t size;
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 	dbug_enter("maptbl_setup");
397*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
398*0Sstevel@tonic-gate 	dbug_precond(filename);
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 	/* clean up from a previous setup */
401*0Sstevel@tonic-gate 	maptbl_teardown(maptbl_object_p);
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 	strlcpy(maptbl_object_p->i_name, filename,
404*0Sstevel@tonic-gate 	    sizeof (maptbl_object_p->i_name));
405*0Sstevel@tonic-gate 	dbug_print(("info", "filename %s", maptbl_object_p->i_name));
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	/* get the page info */
408*0Sstevel@tonic-gate 	maptbl_object_p->i_pagesize = PAGESIZE;
409*0Sstevel@tonic-gate 	maptbl_object_p->i_pagemask = PAGEMASK;
410*0Sstevel@tonic-gate 	maptbl_object_p->i_maplen = maptbl_object_p->i_pagesize * 100;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	/* open the file */
413*0Sstevel@tonic-gate 	maptbl_object_p->i_fid = open(maptbl_object_p->i_name,
414*0Sstevel@tonic-gate 	    O_RDWR | O_NONBLOCK);
415*0Sstevel@tonic-gate 	if (maptbl_object_p->i_fid == -1) {
416*0Sstevel@tonic-gate 		xx = errno;
417*0Sstevel@tonic-gate 		dbug_print(("error",
418*0Sstevel@tonic-gate 		    "Could not open %s, %d", maptbl_object_p->i_name, xx));
419*0Sstevel@tonic-gate 		dbug_leave("maptbl_setup");
420*0Sstevel@tonic-gate 		return (xx);
421*0Sstevel@tonic-gate 	}
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 	/* get the size and type of file */
424*0Sstevel@tonic-gate 	xx = fstat(maptbl_object_p->i_fid, &sinfo);
425*0Sstevel@tonic-gate 	if (xx) {
426*0Sstevel@tonic-gate 		xx = errno;
427*0Sstevel@tonic-gate 		dbug_print(("error",
428*0Sstevel@tonic-gate 		    "Could not stat %s, %d", maptbl_object_p->i_name, xx));
429*0Sstevel@tonic-gate 		dbug_leave("maptbl_setup");
430*0Sstevel@tonic-gate 		return (xx);
431*0Sstevel@tonic-gate 	}
432*0Sstevel@tonic-gate 	maptbl_object_p->i_size = sinfo.st_size;
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate 	/* sanity check, better be a regular file */
435*0Sstevel@tonic-gate 	if (!S_ISREG(sinfo.st_mode)) {
436*0Sstevel@tonic-gate 		xx = ENOTSUP;
437*0Sstevel@tonic-gate 		dbug_print(("error",
438*0Sstevel@tonic-gate 		    "%s Not a regular file.", maptbl_object_p->i_name));
439*0Sstevel@tonic-gate 		dbug_leave("maptbl_setup");
440*0Sstevel@tonic-gate 		return (xx);
441*0Sstevel@tonic-gate 	}
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate 	/* determine number of entries */
444*0Sstevel@tonic-gate 	maptbl_object_p->i_entries =
445*0Sstevel@tonic-gate 	    maptbl_object_p->i_size / sizeof (struct cfs_dlog_mapping_space);
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	/* set up modulo value for second hash function */
448*0Sstevel@tonic-gate 	maptbl_object_p->i_hash2mod = (maptbl_object_p->i_entries / 2) + 1;
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	/* initialize statistic gathering */
451*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_requests = 0;
452*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_probes = 0;
453*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_mapmove = 0;
454*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_mapdist = 0;
455*0Sstevel@tonic-gate 	maptbl_object_p->i_stat_filled = 0;
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 	/* zero the file */
458*0Sstevel@tonic-gate 	for (offset = 0; offset < maptbl_object_p->i_size;
459*0Sstevel@tonic-gate 		offset += maptbl_object_p->i_maplen) {
460*0Sstevel@tonic-gate 		/* map in a section of the file */
461*0Sstevel@tonic-gate 		xx = maptbl_domap(maptbl_object_p, offset);
462*0Sstevel@tonic-gate 		if (xx) {
463*0Sstevel@tonic-gate 			dbug_leave("maptbl_setup");
464*0Sstevel@tonic-gate 			return (xx);
465*0Sstevel@tonic-gate 		}
466*0Sstevel@tonic-gate 		/* zero this section of the file */
467*0Sstevel@tonic-gate 		lp = (long *)maptbl_object_p->i_pa;
468*0Sstevel@tonic-gate 		size = maptbl_object_p->i_size - offset;
469*0Sstevel@tonic-gate 		if (size < maptbl_object_p->i_palen) {
470*0Sstevel@tonic-gate 			cnt = size / sizeof (long);
471*0Sstevel@tonic-gate 		} else {
472*0Sstevel@tonic-gate 			cnt = maptbl_object_p->i_palen / sizeof (long);
473*0Sstevel@tonic-gate 			dbug_assert((cnt * sizeof (long)) ==
474*0Sstevel@tonic-gate 			    maptbl_object_p->i_palen);
475*0Sstevel@tonic-gate 		}
476*0Sstevel@tonic-gate 		memset(lp, 0, cnt * sizeof (*lp));
477*0Sstevel@tonic-gate 	}
478*0Sstevel@tonic-gate 
479*0Sstevel@tonic-gate 	/* return success */
480*0Sstevel@tonic-gate 	dbug_leave("maptbl_setup");
481*0Sstevel@tonic-gate 	return (0);
482*0Sstevel@tonic-gate }
483*0Sstevel@tonic-gate 
484*0Sstevel@tonic-gate /*
485*0Sstevel@tonic-gate  *			maptbl_teardown
486*0Sstevel@tonic-gate  *
487*0Sstevel@tonic-gate  * Description:
488*0Sstevel@tonic-gate  * Arguments:
489*0Sstevel@tonic-gate  * Returns:
490*0Sstevel@tonic-gate  * Preconditions:
491*0Sstevel@tonic-gate  */
492*0Sstevel@tonic-gate void
maptbl_teardown(cfsd_maptbl_object_t * maptbl_object_p)493*0Sstevel@tonic-gate maptbl_teardown(cfsd_maptbl_object_t *maptbl_object_p)
494*0Sstevel@tonic-gate {
495*0Sstevel@tonic-gate 	int xx;
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate 	dbug_enter("maptbl_teardown");
498*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate 	if (maptbl_object_p->i_pa) {
501*0Sstevel@tonic-gate 		xx = munmap(maptbl_object_p->i_pa, maptbl_object_p->i_palen);
502*0Sstevel@tonic-gate 		if (xx == -1) {
503*0Sstevel@tonic-gate 			xx = errno;
504*0Sstevel@tonic-gate 			dbug_print(("error", "Could not unmap %s, %d, %p, %d",
505*0Sstevel@tonic-gate 			    maptbl_object_p->i_name, xx, maptbl_object_p->i_pa,
506*0Sstevel@tonic-gate 			    maptbl_object_p->i_palen));
507*0Sstevel@tonic-gate 		}
508*0Sstevel@tonic-gate 		maptbl_object_p->i_pa = NULL;
509*0Sstevel@tonic-gate 	}
510*0Sstevel@tonic-gate 	maptbl_object_p->i_paoff = 0;
511*0Sstevel@tonic-gate 	maptbl_object_p->i_paend = 0;
512*0Sstevel@tonic-gate 	maptbl_object_p->i_palen = 0;
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate 	if (maptbl_object_p->i_fid != -1) {
515*0Sstevel@tonic-gate 		if (close(maptbl_object_p->i_fid))
516*0Sstevel@tonic-gate 			dbug_print(("err", "cannot close maptbl fd, error %d",
517*0Sstevel@tonic-gate 			    errno));
518*0Sstevel@tonic-gate 		maptbl_object_p->i_fid = -1;
519*0Sstevel@tonic-gate 	}
520*0Sstevel@tonic-gate 	dbug_leave("maptbl_teardown");
521*0Sstevel@tonic-gate }
522*0Sstevel@tonic-gate 
523*0Sstevel@tonic-gate /*
524*0Sstevel@tonic-gate  *			maptbl_get
525*0Sstevel@tonic-gate  *
526*0Sstevel@tonic-gate  * Description:
527*0Sstevel@tonic-gate  *	Gets the mapping info for the specified cid.
528*0Sstevel@tonic-gate  * Arguments:
529*0Sstevel@tonic-gate  *	cid
530*0Sstevel@tonic-gate  *	valuep
531*0Sstevel@tonic-gate  * Returns:
532*0Sstevel@tonic-gate  *	Returns 0 for success, 1 if entry not found, -1 if an
533*0Sstevel@tonic-gate  *	error occurs in the mapping file.
534*0Sstevel@tonic-gate  * Preconditions:
535*0Sstevel@tonic-gate  *	precond(valuep)
536*0Sstevel@tonic-gate  */
537*0Sstevel@tonic-gate int
maptbl_get(cfsd_maptbl_object_t * maptbl_object_p,cfs_cid_t cid,struct cfs_dlog_mapping_space * valuep)538*0Sstevel@tonic-gate maptbl_get(cfsd_maptbl_object_t *maptbl_object_p,
539*0Sstevel@tonic-gate 	cfs_cid_t cid,
540*0Sstevel@tonic-gate 	struct cfs_dlog_mapping_space *valuep)
541*0Sstevel@tonic-gate {
542*0Sstevel@tonic-gate 	int xx;
543*0Sstevel@tonic-gate 	struct cfs_dlog_mapping_space *pa;
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate 	dbug_enter("maptbl_get");
546*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
547*0Sstevel@tonic-gate 	dbug_precond(valuep);
548*0Sstevel@tonic-gate 
549*0Sstevel@tonic-gate 	if (maptbl_object_p->i_entries == 0) {
550*0Sstevel@tonic-gate 		dbug_leave("maptbl_get");
551*0Sstevel@tonic-gate 		return (1);
552*0Sstevel@tonic-gate 	}
553*0Sstevel@tonic-gate 	xx = maptbl_cidhashaddr(maptbl_object_p, cid, (caddr_t *)&pa);
554*0Sstevel@tonic-gate 	if (xx == 0)
555*0Sstevel@tonic-gate 		*valuep = *pa;
556*0Sstevel@tonic-gate 	dbug_leave("maptbl_get");
557*0Sstevel@tonic-gate 	return (xx);
558*0Sstevel@tonic-gate }
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate /*
561*0Sstevel@tonic-gate  *			maptbl_set
562*0Sstevel@tonic-gate  *
563*0Sstevel@tonic-gate  * Description:
564*0Sstevel@tonic-gate  *	Sets the mapping info for the cid.
565*0Sstevel@tonic-gate  *	If insert is 1 then if the entry is not found it is put in the
566*0Sstevel@tonic-gate  *	table.
567*0Sstevel@tonic-gate  * Arguments:
568*0Sstevel@tonic-gate  *	valuep
569*0Sstevel@tonic-gate  *	insert
570*0Sstevel@tonic-gate  * Returns:
571*0Sstevel@tonic-gate  *	Returns 0 if mapping info placed in the table, 1 if entry
572*0Sstevel@tonic-gate  *	is not found an insert is 0, -1 if an error occurs in the
573*0Sstevel@tonic-gate  *	mapping file.
574*0Sstevel@tonic-gate  * Preconditions:
575*0Sstevel@tonic-gate  *	precond(valuep)
576*0Sstevel@tonic-gate  */
577*0Sstevel@tonic-gate int
maptbl_set(cfsd_maptbl_object_t * maptbl_object_p,struct cfs_dlog_mapping_space * valuep,int insert)578*0Sstevel@tonic-gate maptbl_set(cfsd_maptbl_object_t *maptbl_object_p,
579*0Sstevel@tonic-gate 	struct cfs_dlog_mapping_space *valuep,
580*0Sstevel@tonic-gate 	int insert)
581*0Sstevel@tonic-gate {
582*0Sstevel@tonic-gate 	int xx;
583*0Sstevel@tonic-gate 	struct cfs_dlog_mapping_space *pa;
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate 	dbug_enter("maptbl_set");
586*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
587*0Sstevel@tonic-gate 	dbug_precond(valuep);
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate 	dbug_assert(maptbl_object_p->i_entries > 0);
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 	xx = maptbl_cidhashaddr(maptbl_object_p, valuep->ms_cid,
592*0Sstevel@tonic-gate 	    (caddr_t *)&pa);
593*0Sstevel@tonic-gate 	if ((xx == 0) || ((xx == 1) && insert)) {
594*0Sstevel@tonic-gate 		*pa = *valuep;
595*0Sstevel@tonic-gate 		if (xx == 1)
596*0Sstevel@tonic-gate 			maptbl_object_p->i_stat_filled++;
597*0Sstevel@tonic-gate 		xx = 0;
598*0Sstevel@tonic-gate 	}
599*0Sstevel@tonic-gate 	dbug_leave("maptbl_set");
600*0Sstevel@tonic-gate 	return (xx);
601*0Sstevel@tonic-gate }
602*0Sstevel@tonic-gate 
603*0Sstevel@tonic-gate /*
604*0Sstevel@tonic-gate  *			maptbl_dumpstats
605*0Sstevel@tonic-gate  *
606*0Sstevel@tonic-gate  * Description:
607*0Sstevel@tonic-gate  *	Prints out various stats about the hashing.
608*0Sstevel@tonic-gate  * Arguments:
609*0Sstevel@tonic-gate  * Returns:
610*0Sstevel@tonic-gate  * Preconditions:
611*0Sstevel@tonic-gate  */
612*0Sstevel@tonic-gate void
maptbl_dumpstats(cfsd_maptbl_object_t * maptbl_object_p)613*0Sstevel@tonic-gate maptbl_dumpstats(cfsd_maptbl_object_t *maptbl_object_p)
614*0Sstevel@tonic-gate {
615*0Sstevel@tonic-gate 	int xx;
616*0Sstevel@tonic-gate 	double dd;
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 	dbug_enter("maptbl_dumpstats");
619*0Sstevel@tonic-gate 	dbug_precond(maptbl_object_p);
620*0Sstevel@tonic-gate 
621*0Sstevel@tonic-gate 	dbug_print(("dump", "Total Entries %d", maptbl_object_p->i_entries));
622*0Sstevel@tonic-gate 	dbug_print(("dump", "Filled Entries %d",
623*0Sstevel@tonic-gate 	    maptbl_object_p->i_stat_filled));
624*0Sstevel@tonic-gate 	dbug_print(("dump", "Requests %d", maptbl_object_p->i_stat_requests));
625*0Sstevel@tonic-gate 	dbug_print(("dump", "Probes %d", maptbl_object_p->i_stat_probes));
626*0Sstevel@tonic-gate 	dbug_print(("dump", "Map Moves %d", maptbl_object_p->i_stat_mapmove));
627*0Sstevel@tonic-gate 	dbug_print(("dump", "Mapping Size %d", maptbl_object_p->i_maplen));
628*0Sstevel@tonic-gate 	dbug_print(("dump", "File Size %d", maptbl_object_p->i_size));
629*0Sstevel@tonic-gate 	if (maptbl_object_p->i_stat_requests == 0) {
630*0Sstevel@tonic-gate 		dbug_leave("maptbl_dumpstats");
631*0Sstevel@tonic-gate 		return;
632*0Sstevel@tonic-gate 	}
633*0Sstevel@tonic-gate 	dd = (double)maptbl_object_p->i_stat_probes /
634*0Sstevel@tonic-gate 	    maptbl_object_p->i_stat_requests;
635*0Sstevel@tonic-gate 	dbug_print(("dump", "Probes per Request %.2f", dd));
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 	dd = (double)maptbl_object_p->i_stat_mapmove /
638*0Sstevel@tonic-gate 	    maptbl_object_p->i_stat_requests;
639*0Sstevel@tonic-gate 	dbug_print(("dump", "Mmap moves per Request %.2f", dd));
640*0Sstevel@tonic-gate 
641*0Sstevel@tonic-gate 	xx = maptbl_object_p->i_stat_mapdist / maptbl_object_p->i_stat_mapmove;
642*0Sstevel@tonic-gate 	dbug_print(("dump", "Average distance per mmap moves %d", xx));
643*0Sstevel@tonic-gate 
644*0Sstevel@tonic-gate 	xx = ((100.0 * maptbl_object_p->i_stat_filled) /
645*0Sstevel@tonic-gate 	    maptbl_object_p->i_entries) + .5;
646*0Sstevel@tonic-gate 	dbug_print(("dump", "Table filled %d%%", xx));
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate 	dbug_leave("maptbl_dumpstats");
649*0Sstevel@tonic-gate }
650