xref: /onnv-gate/usr/src/cmd/ndmpd/tlm/tlm_bitmap.c (revision 7917:5c4442486198)
1*7917SReza.Sabdar@Sun.COM /*
2*7917SReza.Sabdar@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3*7917SReza.Sabdar@Sun.COM  * Use is subject to license terms.
4*7917SReza.Sabdar@Sun.COM  */
5*7917SReza.Sabdar@Sun.COM 
6*7917SReza.Sabdar@Sun.COM /*
7*7917SReza.Sabdar@Sun.COM  * BSD 3 Clause License
8*7917SReza.Sabdar@Sun.COM  *
9*7917SReza.Sabdar@Sun.COM  * Copyright (c) 2007, The Storage Networking Industry Association.
10*7917SReza.Sabdar@Sun.COM  *
11*7917SReza.Sabdar@Sun.COM  * Redistribution and use in source and binary forms, with or without
12*7917SReza.Sabdar@Sun.COM  * modification, are permitted provided that the following conditions
13*7917SReza.Sabdar@Sun.COM  * are met:
14*7917SReza.Sabdar@Sun.COM  * 	- Redistributions of source code must retain the above copyright
15*7917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer.
16*7917SReza.Sabdar@Sun.COM  *
17*7917SReza.Sabdar@Sun.COM  * 	- Redistributions in binary form must reproduce the above copyright
18*7917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer in
19*7917SReza.Sabdar@Sun.COM  *	  the documentation and/or other materials provided with the
20*7917SReza.Sabdar@Sun.COM  *	  distribution.
21*7917SReza.Sabdar@Sun.COM  *
22*7917SReza.Sabdar@Sun.COM  *	- Neither the name of The Storage Networking Industry Association (SNIA)
23*7917SReza.Sabdar@Sun.COM  *	  nor the names of its contributors may be used to endorse or promote
24*7917SReza.Sabdar@Sun.COM  *	  products derived from this software without specific prior written
25*7917SReza.Sabdar@Sun.COM  *	  permission.
26*7917SReza.Sabdar@Sun.COM  *
27*7917SReza.Sabdar@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28*7917SReza.Sabdar@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29*7917SReza.Sabdar@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30*7917SReza.Sabdar@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31*7917SReza.Sabdar@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*7917SReza.Sabdar@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*7917SReza.Sabdar@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*7917SReza.Sabdar@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*7917SReza.Sabdar@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*7917SReza.Sabdar@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*7917SReza.Sabdar@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
38*7917SReza.Sabdar@Sun.COM  */
39*7917SReza.Sabdar@Sun.COM #include <sys/types.h>
40*7917SReza.Sabdar@Sun.COM #include <sys/queue.h>
41*7917SReza.Sabdar@Sun.COM #include <bitmap.h>
42*7917SReza.Sabdar@Sun.COM #include <fcntl.h>
43*7917SReza.Sabdar@Sun.COM #include <stdio.h>
44*7917SReza.Sabdar@Sun.COM #include <stdlib.h>
45*7917SReza.Sabdar@Sun.COM #include <string.h>
46*7917SReza.Sabdar@Sun.COM #include <time.h>
47*7917SReza.Sabdar@Sun.COM #include <unistd.h>
48*7917SReza.Sabdar@Sun.COM #include <tlm.h>
49*7917SReza.Sabdar@Sun.COM 
50*7917SReza.Sabdar@Sun.COM 
51*7917SReza.Sabdar@Sun.COM /*
52*7917SReza.Sabdar@Sun.COM  * Hash table size.
53*7917SReza.Sabdar@Sun.COM  */
54*7917SReza.Sabdar@Sun.COM #define	BMAP_HASH_SIZE		64
55*7917SReza.Sabdar@Sun.COM 
56*7917SReza.Sabdar@Sun.COM 
57*7917SReza.Sabdar@Sun.COM /*
58*7917SReza.Sabdar@Sun.COM  * Maximum number of chunk that can be cached.
59*7917SReza.Sabdar@Sun.COM  */
60*7917SReza.Sabdar@Sun.COM #define	BMAP_CHUNK_MAX		128
61*7917SReza.Sabdar@Sun.COM 
62*7917SReza.Sabdar@Sun.COM 
63*7917SReza.Sabdar@Sun.COM /*
64*7917SReza.Sabdar@Sun.COM  * Size of bitmap table.
65*7917SReza.Sabdar@Sun.COM  */
66*7917SReza.Sabdar@Sun.COM #define	BMAP_MAX	256
67*7917SReza.Sabdar@Sun.COM 
68*7917SReza.Sabdar@Sun.COM 
69*7917SReza.Sabdar@Sun.COM /*
70*7917SReza.Sabdar@Sun.COM  * Bit_MAP Word SIZE.  This should be equal to 'sizeof (int)'.
71*7917SReza.Sabdar@Sun.COM  */
72*7917SReza.Sabdar@Sun.COM #define	BMAP_WSIZE	(sizeof (int))
73*7917SReza.Sabdar@Sun.COM 
74*7917SReza.Sabdar@Sun.COM 
75*7917SReza.Sabdar@Sun.COM /*
76*7917SReza.Sabdar@Sun.COM  * Bit_MAP Bit Per Word.
77*7917SReza.Sabdar@Sun.COM  */
78*7917SReza.Sabdar@Sun.COM #define	BMAP_BPW	(BMAP_WSIZE * 8)
79*7917SReza.Sabdar@Sun.COM #define	BMAP_BPW_SHIFT	5
80*7917SReza.Sabdar@Sun.COM #define	BMAP_BPW_MASK	(~(~0 << BMAP_BPW_SHIFT))
81*7917SReza.Sabdar@Sun.COM 
82*7917SReza.Sabdar@Sun.COM 
83*7917SReza.Sabdar@Sun.COM /*
84*7917SReza.Sabdar@Sun.COM  * Chunk of bit map in each node.
85*7917SReza.Sabdar@Sun.COM  */
86*7917SReza.Sabdar@Sun.COM #define	BMAP_CHUNK_WORDS	1024
87*7917SReza.Sabdar@Sun.COM #define	BMAP_CHUNK_BYTES	(BMAP_CHUNK_WORDS * BMAP_WSIZE)
88*7917SReza.Sabdar@Sun.COM #define	BMAP_CHUNK_BITS		(BMAP_CHUNK_WORDS * BMAP_BPW)
89*7917SReza.Sabdar@Sun.COM #define	BMAP_CHUNK_NO(p)	((p) / BMAP_CHUNK_BITS)
90*7917SReza.Sabdar@Sun.COM #define	BMAP_CHUNK_OFF(p)	(BMAP_CHUNK_NO(p) * BMAP_CHUNK_BITS)
91*7917SReza.Sabdar@Sun.COM 
92*7917SReza.Sabdar@Sun.COM 
93*7917SReza.Sabdar@Sun.COM /*
94*7917SReza.Sabdar@Sun.COM  * Bitmap flags.
95*7917SReza.Sabdar@Sun.COM  */
96*7917SReza.Sabdar@Sun.COM #define	BMAP_BINIT_ONES	0x00000001 /* initial value of bits is 1 */
97*7917SReza.Sabdar@Sun.COM #define	BMAP_INUSE	0x00000002 /* slot is in use */
98*7917SReza.Sabdar@Sun.COM 
99*7917SReza.Sabdar@Sun.COM 
100*7917SReza.Sabdar@Sun.COM /*
101*7917SReza.Sabdar@Sun.COM  * Macros of bitmap flags.
102*7917SReza.Sabdar@Sun.COM  */
103*7917SReza.Sabdar@Sun.COM #define	BMAP_SET_FLAGS(b, f)	((b)->bm_flags |= (f))
104*7917SReza.Sabdar@Sun.COM #define	BMAP_UNSET_FLAGS(b, f)	((b)->bm_flags &= ~(f))
105*7917SReza.Sabdar@Sun.COM 
106*7917SReza.Sabdar@Sun.COM #define	BMAP_IS_INIT_ONES(b)	((b)->bm_flags & BMAP_BINIT_ONES)
107*7917SReza.Sabdar@Sun.COM #define	BMAP_IS_INUSE(b)	((b)->bm_flags & BMAP_INUSE)
108*7917SReza.Sabdar@Sun.COM 
109*7917SReza.Sabdar@Sun.COM 
110*7917SReza.Sabdar@Sun.COM #define	HASH(p)		(((p) / BMAP_CHUNK_BITS) % BMAP_HASH_SIZE)
111*7917SReza.Sabdar@Sun.COM 
112*7917SReza.Sabdar@Sun.COM /*
113*7917SReza.Sabdar@Sun.COM  * Calculate the memory size in bytes needed for the specified length
114*7917SReza.Sabdar@Sun.COM  * of bitmap.
115*7917SReza.Sabdar@Sun.COM  */
116*7917SReza.Sabdar@Sun.COM #define	ROUNDUP(n, d)	(((n) + (d) - 1) / (d))
117*7917SReza.Sabdar@Sun.COM #define	MEM_LEN(l)	(ROUNDUP((l), BMAP_BPW) * BMAP_WSIZE)
118*7917SReza.Sabdar@Sun.COM 
119*7917SReza.Sabdar@Sun.COM 
120*7917SReza.Sabdar@Sun.COM /*
121*7917SReza.Sabdar@Sun.COM  * Chunk flags.
122*7917SReza.Sabdar@Sun.COM  */
123*7917SReza.Sabdar@Sun.COM #define	BMAP_CSET_DIRTY(cp)	(cp)->c_flags |= BMAP_CDIRTY
124*7917SReza.Sabdar@Sun.COM #define	BMAP_CDIRTY	0x00000001 /* the chunk is dirty */
125*7917SReza.Sabdar@Sun.COM 
126*7917SReza.Sabdar@Sun.COM 
127*7917SReza.Sabdar@Sun.COM /*
128*7917SReza.Sabdar@Sun.COM  * Macros on chunk flags.
129*7917SReza.Sabdar@Sun.COM  */
130*7917SReza.Sabdar@Sun.COM #define	BMAP_CIS_DIRTY(cp)	((cp)->c_flags & BMAP_CDIRTY)
131*7917SReza.Sabdar@Sun.COM 
132*7917SReza.Sabdar@Sun.COM 
133*7917SReza.Sabdar@Sun.COM /*
134*7917SReza.Sabdar@Sun.COM  * When loading a bitmap chunk, if it is new set the bitmap
135*7917SReza.Sabdar@Sun.COM  * can be set according to the initial value of bits.
136*7917SReza.Sabdar@Sun.COM  * Otherwise, it should be loaded from the file.
137*7917SReza.Sabdar@Sun.COM  */
138*7917SReza.Sabdar@Sun.COM #define	BMAP_NEW_CHUNK		1
139*7917SReza.Sabdar@Sun.COM #define	BMAP_OLD_CHUNK		0
140*7917SReza.Sabdar@Sun.COM 
141*7917SReza.Sabdar@Sun.COM /*
142*7917SReza.Sabdar@Sun.COM  * Each chunk holds the followin information:
143*7917SReza.Sabdar@Sun.COM  *  - A flag showing the status of the chunk, like being ditry or not.
144*7917SReza.Sabdar@Sun.COM  *  - Its offset in bits from the beginning of the vector.
145*7917SReza.Sabdar@Sun.COM  *  - Its length in bits.
146*7917SReza.Sabdar@Sun.COM  *  - Its memory length in use in bytes.
147*7917SReza.Sabdar@Sun.COM  *  - The bitmap vector.
148*7917SReza.Sabdar@Sun.COM  *
149*7917SReza.Sabdar@Sun.COM  *  In addition to the above information, each chunk can be on two lists:
150*7917SReza.Sabdar@Sun.COM  *  one the hash list, the other LRU list.  The hash list is a MRU list,
151*7917SReza.Sabdar@Sun.COM  *  meaning the MRU entry is at the head of the list.
152*7917SReza.Sabdar@Sun.COM  *
153*7917SReza.Sabdar@Sun.COM  *  All the chunks are in the LRU list. When a chunk is needed and there is
154*7917SReza.Sabdar@Sun.COM  *  no more room for allocating chunks, the first entry of this list is
155*7917SReza.Sabdar@Sun.COM  *  reclaimed.
156*7917SReza.Sabdar@Sun.COM  */
157*7917SReza.Sabdar@Sun.COM typedef struct dbmap_chunk {
158*7917SReza.Sabdar@Sun.COM 	TAILQ_ENTRY(dbmap_chunk) c_hash;
159*7917SReza.Sabdar@Sun.COM 	TAILQ_ENTRY(dbmap_chunk) c_lru;
160*7917SReza.Sabdar@Sun.COM 	uint_t c_flags;
161*7917SReza.Sabdar@Sun.COM 	u_quad_t c_off;
162*7917SReza.Sabdar@Sun.COM 	uint_t c_clen;
163*7917SReza.Sabdar@Sun.COM 	uint_t c_mlen;
164*7917SReza.Sabdar@Sun.COM 	uint_t *c_bmp;
165*7917SReza.Sabdar@Sun.COM } dbmap_chunk_t;
166*7917SReza.Sabdar@Sun.COM 
167*7917SReza.Sabdar@Sun.COM 
168*7917SReza.Sabdar@Sun.COM TAILQ_HEAD(dbmap_list, dbmap_chunk);
169*7917SReza.Sabdar@Sun.COM typedef struct dbmap_list dbmap_list_t;
170*7917SReza.Sabdar@Sun.COM 
171*7917SReza.Sabdar@Sun.COM 
172*7917SReza.Sabdar@Sun.COM typedef struct dbitmap {
173*7917SReza.Sabdar@Sun.COM 	char *bm_fname;
174*7917SReza.Sabdar@Sun.COM 	int bm_fd;
175*7917SReza.Sabdar@Sun.COM 	uint_t bm_flags;
176*7917SReza.Sabdar@Sun.COM 	u_quad_t bm_len; /* bitmap length */
177*7917SReza.Sabdar@Sun.COM 	uint_t bm_cmax; /* maximum number of cached chunks */
178*7917SReza.Sabdar@Sun.COM 	uint_t bm_ccur; /* current number of cached chunks */
179*7917SReza.Sabdar@Sun.COM 	dbmap_list_t bm_hash[BMAP_HASH_SIZE]; /* MRU hash table */
180*7917SReza.Sabdar@Sun.COM 	dbmap_list_t bm_lru; /* LRU list */
181*7917SReza.Sabdar@Sun.COM } dbitmap_t;
182*7917SReza.Sabdar@Sun.COM 
183*7917SReza.Sabdar@Sun.COM /*
184*7917SReza.Sabdar@Sun.COM  * Disk bitmap table.  Upon allocating a dbitmap, one slot
185*7917SReza.Sabdar@Sun.COM  * of this table will be used.
186*7917SReza.Sabdar@Sun.COM  */
187*7917SReza.Sabdar@Sun.COM static dbitmap_t dbitmap[BMAP_MAX];
188*7917SReza.Sabdar@Sun.COM 
189*7917SReza.Sabdar@Sun.COM 
190*7917SReza.Sabdar@Sun.COM /*
191*7917SReza.Sabdar@Sun.COM  * Each chunk holds the followin information:
192*7917SReza.Sabdar@Sun.COM  *  - Its offset in bits from the beginning of the vector.
193*7917SReza.Sabdar@Sun.COM  *  - Its length in bits.
194*7917SReza.Sabdar@Sun.COM  *  - Its memory length in use in bytes.
195*7917SReza.Sabdar@Sun.COM  *  - The bitmap vector.
196*7917SReza.Sabdar@Sun.COM  *
197*7917SReza.Sabdar@Sun.COM  *  In addition to the above information, each chunk can be on a list:
198*7917SReza.Sabdar@Sun.COM  *  one the hash list.  The hash list is a MRU list,  meaning that the
199*7917SReza.Sabdar@Sun.COM  *  MRU entry is at the head of the list.
200*7917SReza.Sabdar@Sun.COM  */
201*7917SReza.Sabdar@Sun.COM typedef struct bmap_chunk {
202*7917SReza.Sabdar@Sun.COM 	TAILQ_ENTRY(bmap_chunk) c_hash;
203*7917SReza.Sabdar@Sun.COM 	u_quad_t c_off;
204*7917SReza.Sabdar@Sun.COM 	uint_t c_clen;
205*7917SReza.Sabdar@Sun.COM 	uint_t c_mlen;
206*7917SReza.Sabdar@Sun.COM 	uint_t *c_bmp;
207*7917SReza.Sabdar@Sun.COM } bmap_chunk_t;
208*7917SReza.Sabdar@Sun.COM 
209*7917SReza.Sabdar@Sun.COM 
210*7917SReza.Sabdar@Sun.COM TAILQ_HEAD(bmap_list, bmap_chunk);
211*7917SReza.Sabdar@Sun.COM typedef struct bmap_list bmap_list_t;
212*7917SReza.Sabdar@Sun.COM 
213*7917SReza.Sabdar@Sun.COM 
214*7917SReza.Sabdar@Sun.COM typedef struct bitmap {
215*7917SReza.Sabdar@Sun.COM 	uint_t bm_flags;
216*7917SReza.Sabdar@Sun.COM 	u_quad_t bm_len; /* bitmap length */
217*7917SReza.Sabdar@Sun.COM 	uint_t bm_cmax; /* maximum number of cached chunks */
218*7917SReza.Sabdar@Sun.COM 	uint_t bm_ccur; /* current number of cached chunks */
219*7917SReza.Sabdar@Sun.COM 	bmap_list_t bm_hash[BMAP_HASH_SIZE]; /* MRU hash table */
220*7917SReza.Sabdar@Sun.COM } bitmap_t;
221*7917SReza.Sabdar@Sun.COM 
222*7917SReza.Sabdar@Sun.COM 
223*7917SReza.Sabdar@Sun.COM /*
224*7917SReza.Sabdar@Sun.COM  * Statistics gathering structure.
225*7917SReza.Sabdar@Sun.COM  */
226*7917SReza.Sabdar@Sun.COM typedef struct bitmap_stats {
227*7917SReza.Sabdar@Sun.COM 	ulong_t bs_alloc_cnt;
228*7917SReza.Sabdar@Sun.COM 	ulong_t bs_alloc_size;
229*7917SReza.Sabdar@Sun.COM 	ulong_t bs_free_cnt;
230*7917SReza.Sabdar@Sun.COM 	ulong_t bs_set_applied;
231*7917SReza.Sabdar@Sun.COM 	ulong_t bs_unset_applied;
232*7917SReza.Sabdar@Sun.COM 	ulong_t bs_cache_hit;
233*7917SReza.Sabdar@Sun.COM 	ulong_t bs_cache_miss;
234*7917SReza.Sabdar@Sun.COM 	ulong_t bs_chunk_new;
235*7917SReza.Sabdar@Sun.COM 	ulong_t bs_chunk_flush;
236*7917SReza.Sabdar@Sun.COM 	ulong_t bs_chunk_reclaim;
237*7917SReza.Sabdar@Sun.COM 	u_quad_t bs_get;
238*7917SReza.Sabdar@Sun.COM 	u_quad_t bs_get_bits;
239*7917SReza.Sabdar@Sun.COM 	u_quad_t bs_set;
240*7917SReza.Sabdar@Sun.COM 	u_quad_t bs_set_bits;
241*7917SReza.Sabdar@Sun.COM 	u_quad_t bs_unset;
242*7917SReza.Sabdar@Sun.COM 	u_quad_t bs_unset_bits;
243*7917SReza.Sabdar@Sun.COM } bitmap_stats_t;
244*7917SReza.Sabdar@Sun.COM 
245*7917SReza.Sabdar@Sun.COM 
246*7917SReza.Sabdar@Sun.COM /*
247*7917SReza.Sabdar@Sun.COM  * Disk bitmap table.  Upon allocating a bitmap, one slot
248*7917SReza.Sabdar@Sun.COM  * of this table will be used.
249*7917SReza.Sabdar@Sun.COM  */
250*7917SReza.Sabdar@Sun.COM static bitmap_t bitmap[BMAP_MAX];
251*7917SReza.Sabdar@Sun.COM 
252*7917SReza.Sabdar@Sun.COM 
253*7917SReza.Sabdar@Sun.COM /*
254*7917SReza.Sabdar@Sun.COM  * Global instance of statistics variable.
255*7917SReza.Sabdar@Sun.COM  */
256*7917SReza.Sabdar@Sun.COM bitmap_stats_t bitmap_stats;
257*7917SReza.Sabdar@Sun.COM 
258*7917SReza.Sabdar@Sun.COM 
259*7917SReza.Sabdar@Sun.COM /*
260*7917SReza.Sabdar@Sun.COM  * bmd2bmp
261*7917SReza.Sabdar@Sun.COM  *
262*7917SReza.Sabdar@Sun.COM  * Convert bitmap descriptor to bitmap pointer.
263*7917SReza.Sabdar@Sun.COM  */
264*7917SReza.Sabdar@Sun.COM static bitmap_t *
265*7917SReza.Sabdar@Sun.COM bmd2bmp(int bmd)
266*7917SReza.Sabdar@Sun.COM {
267*7917SReza.Sabdar@Sun.COM 	if (bmd < 0 || bmd >= BMAP_MAX)
268*7917SReza.Sabdar@Sun.COM 		return (NULL);
269*7917SReza.Sabdar@Sun.COM 
270*7917SReza.Sabdar@Sun.COM 	return (&bitmap[bmd]);
271*7917SReza.Sabdar@Sun.COM }
272*7917SReza.Sabdar@Sun.COM 
273*7917SReza.Sabdar@Sun.COM 
274*7917SReza.Sabdar@Sun.COM /*
275*7917SReza.Sabdar@Sun.COM  * bmd_alloc
276*7917SReza.Sabdar@Sun.COM  *
277*7917SReza.Sabdar@Sun.COM  * Allocate a bitmap descriptor.  Sets the INUSE flag of the slot.
278*7917SReza.Sabdar@Sun.COM  */
279*7917SReza.Sabdar@Sun.COM static int
280*7917SReza.Sabdar@Sun.COM bmd_alloc(void)
281*7917SReza.Sabdar@Sun.COM {
282*7917SReza.Sabdar@Sun.COM 	int i;
283*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
284*7917SReza.Sabdar@Sun.COM 
285*7917SReza.Sabdar@Sun.COM 	bmp = bitmap;
286*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_MAX; bmp++, i++)
287*7917SReza.Sabdar@Sun.COM 		if (!BMAP_IS_INUSE(bmp)) {
288*7917SReza.Sabdar@Sun.COM 			BMAP_SET_FLAGS(bmp, BMAP_INUSE);
289*7917SReza.Sabdar@Sun.COM 			return (i);
290*7917SReza.Sabdar@Sun.COM 		}
291*7917SReza.Sabdar@Sun.COM 
292*7917SReza.Sabdar@Sun.COM 	return (-1);
293*7917SReza.Sabdar@Sun.COM }
294*7917SReza.Sabdar@Sun.COM 
295*7917SReza.Sabdar@Sun.COM 
296*7917SReza.Sabdar@Sun.COM /*
297*7917SReza.Sabdar@Sun.COM  * bmd_free
298*7917SReza.Sabdar@Sun.COM  *
299*7917SReza.Sabdar@Sun.COM  * Free a bitmap descriptor.  Clears the INUSE flag of the slot.
300*7917SReza.Sabdar@Sun.COM  */
301*7917SReza.Sabdar@Sun.COM static void
302*7917SReza.Sabdar@Sun.COM bmd_free(int bmd)
303*7917SReza.Sabdar@Sun.COM {
304*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
305*7917SReza.Sabdar@Sun.COM 
306*7917SReza.Sabdar@Sun.COM 	bmp = bmd2bmp(bmd);
307*7917SReza.Sabdar@Sun.COM 	if (bmp)
308*7917SReza.Sabdar@Sun.COM 		BMAP_UNSET_FLAGS(bmp, BMAP_INUSE);
309*7917SReza.Sabdar@Sun.COM }
310*7917SReza.Sabdar@Sun.COM 
311*7917SReza.Sabdar@Sun.COM 
312*7917SReza.Sabdar@Sun.COM /*
313*7917SReza.Sabdar@Sun.COM  * bmp_set
314*7917SReza.Sabdar@Sun.COM  *
315*7917SReza.Sabdar@Sun.COM  * Generic function to set bit in a chunk.  This can set or unset the
316*7917SReza.Sabdar@Sun.COM  * specified bit.
317*7917SReza.Sabdar@Sun.COM  */
318*7917SReza.Sabdar@Sun.COM static inline int
319*7917SReza.Sabdar@Sun.COM bmp_set(bmap_chunk_t *cp, u_quad_t bn, uint_t *vp)
320*7917SReza.Sabdar@Sun.COM {
321*7917SReza.Sabdar@Sun.COM 	int rv;
322*7917SReza.Sabdar@Sun.COM 	uint_t mask;
323*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
324*7917SReza.Sabdar@Sun.COM 	uint_t v;
325*7917SReza.Sabdar@Sun.COM 
326*7917SReza.Sabdar@Sun.COM 	bn -= cp->c_off;
327*7917SReza.Sabdar@Sun.COM 	if (bn < cp->c_clen) {
328*7917SReza.Sabdar@Sun.COM 		mask = 1 <<(bn & BMAP_BPW_MASK);
329*7917SReza.Sabdar@Sun.COM 		ip = &cp->c_bmp[bn >> BMAP_BPW_SHIFT];
330*7917SReza.Sabdar@Sun.COM 		v = (*vp <<(bn & BMAP_BPW_MASK)) & mask;
331*7917SReza.Sabdar@Sun.COM 		*ip = (*ip & ~mask) | v;
332*7917SReza.Sabdar@Sun.COM 		rv = 0;
333*7917SReza.Sabdar@Sun.COM 	} else
334*7917SReza.Sabdar@Sun.COM 		rv = -ERANGE;
335*7917SReza.Sabdar@Sun.COM 
336*7917SReza.Sabdar@Sun.COM 	return (rv);
337*7917SReza.Sabdar@Sun.COM }
338*7917SReza.Sabdar@Sun.COM 
339*7917SReza.Sabdar@Sun.COM 
340*7917SReza.Sabdar@Sun.COM /*
341*7917SReza.Sabdar@Sun.COM  * bmp_get
342*7917SReza.Sabdar@Sun.COM  *
343*7917SReza.Sabdar@Sun.COM  * Generic function to get bit in a chunk.
344*7917SReza.Sabdar@Sun.COM  */
345*7917SReza.Sabdar@Sun.COM static inline int
346*7917SReza.Sabdar@Sun.COM bmp_get(bmap_chunk_t *cp, u_quad_t bn)
347*7917SReza.Sabdar@Sun.COM {
348*7917SReza.Sabdar@Sun.COM 	int rv;
349*7917SReza.Sabdar@Sun.COM 	uint_t bit;
350*7917SReza.Sabdar@Sun.COM 
351*7917SReza.Sabdar@Sun.COM 	bn -= cp->c_off;
352*7917SReza.Sabdar@Sun.COM 	if (bn < cp->c_clen) {
353*7917SReza.Sabdar@Sun.COM 		bit = 1 <<(bn & BMAP_BPW_MASK);
354*7917SReza.Sabdar@Sun.COM 		rv = (cp->c_bmp[bn >> BMAP_BPW_SHIFT] & bit) != 0;
355*7917SReza.Sabdar@Sun.COM 	} else
356*7917SReza.Sabdar@Sun.COM 		rv = -ERANGE;
357*7917SReza.Sabdar@Sun.COM 
358*7917SReza.Sabdar@Sun.COM 	return (rv);
359*7917SReza.Sabdar@Sun.COM }
360*7917SReza.Sabdar@Sun.COM 
361*7917SReza.Sabdar@Sun.COM 
362*7917SReza.Sabdar@Sun.COM /*
363*7917SReza.Sabdar@Sun.COM  * bm_chuck_setup
364*7917SReza.Sabdar@Sun.COM  *
365*7917SReza.Sabdar@Sun.COM  * Set up the properties of the new chunk and position it in the hash list.
366*7917SReza.Sabdar@Sun.COM  */
367*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
368*7917SReza.Sabdar@Sun.COM bm_chunk_setup(bitmap_t *bmp, bmap_chunk_t *cp, u_quad_t bn)
369*7917SReza.Sabdar@Sun.COM {
370*7917SReza.Sabdar@Sun.COM 	int h;
371*7917SReza.Sabdar@Sun.COM 	u_quad_t off, l;
372*7917SReza.Sabdar@Sun.COM 	uint_t cl, ml;
373*7917SReza.Sabdar@Sun.COM 	bmap_list_t *hp;
374*7917SReza.Sabdar@Sun.COM 
375*7917SReza.Sabdar@Sun.COM 	off = BMAP_CHUNK_OFF(bn);
376*7917SReza.Sabdar@Sun.COM 	l = bmp->bm_len - off;
377*7917SReza.Sabdar@Sun.COM 	if (l >= BMAP_CHUNK_BITS) {
378*7917SReza.Sabdar@Sun.COM 		cl = BMAP_CHUNK_BITS;
379*7917SReza.Sabdar@Sun.COM 		ml = BMAP_CHUNK_BYTES;
380*7917SReza.Sabdar@Sun.COM 	} else {
381*7917SReza.Sabdar@Sun.COM 		cl = l;
382*7917SReza.Sabdar@Sun.COM 		ml = MEM_LEN(l);
383*7917SReza.Sabdar@Sun.COM 	}
384*7917SReza.Sabdar@Sun.COM 
385*7917SReza.Sabdar@Sun.COM 	if (BMAP_IS_INIT_ONES(bmp))
386*7917SReza.Sabdar@Sun.COM 		(void) memset(cp->c_bmp, 0xff, ml);
387*7917SReza.Sabdar@Sun.COM 	else
388*7917SReza.Sabdar@Sun.COM 		(void) memset(cp->c_bmp, 0x00, ml);
389*7917SReza.Sabdar@Sun.COM 
390*7917SReza.Sabdar@Sun.COM 	h = HASH(bn);
391*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
392*7917SReza.Sabdar@Sun.COM 
393*7917SReza.Sabdar@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
394*7917SReza.Sabdar@Sun.COM 	TAILQ_INSERT_HEAD(hp, cp, c_hash);
395*7917SReza.Sabdar@Sun.COM 	cp->c_off = off;
396*7917SReza.Sabdar@Sun.COM 	cp->c_clen = cl;
397*7917SReza.Sabdar@Sun.COM 	cp->c_mlen = ml;
398*7917SReza.Sabdar@Sun.COM 	return (cp);
399*7917SReza.Sabdar@Sun.COM }
400*7917SReza.Sabdar@Sun.COM 
401*7917SReza.Sabdar@Sun.COM 
402*7917SReza.Sabdar@Sun.COM /*
403*7917SReza.Sabdar@Sun.COM  * bm_chunk_new
404*7917SReza.Sabdar@Sun.COM  *
405*7917SReza.Sabdar@Sun.COM  * Create a new chunk and keep track of memory used.
406*7917SReza.Sabdar@Sun.COM  */
407*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
408*7917SReza.Sabdar@Sun.COM bm_chunk_new(bitmap_t *bmp, u_quad_t bn)
409*7917SReza.Sabdar@Sun.COM {
410*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
411*7917SReza.Sabdar@Sun.COM 
412*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_new++;
413*7917SReza.Sabdar@Sun.COM 
414*7917SReza.Sabdar@Sun.COM 	cp = ndmp_malloc(sizeof (bmap_chunk_t));
415*7917SReza.Sabdar@Sun.COM 	if (cp) {
416*7917SReza.Sabdar@Sun.COM 		cp->c_bmp = ndmp_malloc(sizeof (uint_t) * BMAP_CHUNK_WORDS);
417*7917SReza.Sabdar@Sun.COM 		if (!cp->c_bmp) {
418*7917SReza.Sabdar@Sun.COM 			free(cp);
419*7917SReza.Sabdar@Sun.COM 			cp = NULL;
420*7917SReza.Sabdar@Sun.COM 		} else {
421*7917SReza.Sabdar@Sun.COM 			(void) bm_chunk_setup(bmp, cp, bn);
422*7917SReza.Sabdar@Sun.COM 			bmp->bm_ccur++;
423*7917SReza.Sabdar@Sun.COM 		}
424*7917SReza.Sabdar@Sun.COM 	}
425*7917SReza.Sabdar@Sun.COM 
426*7917SReza.Sabdar@Sun.COM 	return (cp);
427*7917SReza.Sabdar@Sun.COM }
428*7917SReza.Sabdar@Sun.COM 
429*7917SReza.Sabdar@Sun.COM 
430*7917SReza.Sabdar@Sun.COM /*
431*7917SReza.Sabdar@Sun.COM  * bm_chunk_alloc
432*7917SReza.Sabdar@Sun.COM  *
433*7917SReza.Sabdar@Sun.COM  * Allocate a chunk and return it.  If the cache for the chunks is not
434*7917SReza.Sabdar@Sun.COM  * fully used, a new chunk is created.
435*7917SReza.Sabdar@Sun.COM  */
436*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
437*7917SReza.Sabdar@Sun.COM bm_chunk_alloc(bitmap_t *bmp, u_quad_t bn)
438*7917SReza.Sabdar@Sun.COM {
439*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
440*7917SReza.Sabdar@Sun.COM 
441*7917SReza.Sabdar@Sun.COM 	if (bmp->bm_ccur < bmp->bm_cmax)
442*7917SReza.Sabdar@Sun.COM 		cp = bm_chunk_new(bmp, bn);
443*7917SReza.Sabdar@Sun.COM 	else
444*7917SReza.Sabdar@Sun.COM 		cp = NULL;
445*7917SReza.Sabdar@Sun.COM 
446*7917SReza.Sabdar@Sun.COM 	return (cp);
447*7917SReza.Sabdar@Sun.COM }
448*7917SReza.Sabdar@Sun.COM 
449*7917SReza.Sabdar@Sun.COM 
450*7917SReza.Sabdar@Sun.COM /*
451*7917SReza.Sabdar@Sun.COM  * hash_free
452*7917SReza.Sabdar@Sun.COM  *
453*7917SReza.Sabdar@Sun.COM  * Free all chunks on the hash list.
454*7917SReza.Sabdar@Sun.COM  */
455*7917SReza.Sabdar@Sun.COM void
456*7917SReza.Sabdar@Sun.COM hash_free(bmap_list_t *hp)
457*7917SReza.Sabdar@Sun.COM {
458*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
459*7917SReza.Sabdar@Sun.COM 
460*7917SReza.Sabdar@Sun.COM 	if (!hp)
461*7917SReza.Sabdar@Sun.COM 		return;
462*7917SReza.Sabdar@Sun.COM 
463*7917SReza.Sabdar@Sun.COM 	while (!TAILQ_EMPTY(hp)) {
464*7917SReza.Sabdar@Sun.COM 		cp = TAILQ_FIRST(hp);
465*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
466*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(hp, cp, c_hash);
467*7917SReza.Sabdar@Sun.COM 		free(cp->c_bmp);
468*7917SReza.Sabdar@Sun.COM 		free(cp);
469*7917SReza.Sabdar@Sun.COM 	}
470*7917SReza.Sabdar@Sun.COM }
471*7917SReza.Sabdar@Sun.COM 
472*7917SReza.Sabdar@Sun.COM 
473*7917SReza.Sabdar@Sun.COM /*
474*7917SReza.Sabdar@Sun.COM  * bm_chunks_free
475*7917SReza.Sabdar@Sun.COM  *
476*7917SReza.Sabdar@Sun.COM  * Release the memory allocated for the chunks.
477*7917SReza.Sabdar@Sun.COM  */
478*7917SReza.Sabdar@Sun.COM static void
479*7917SReza.Sabdar@Sun.COM bm_chunks_free(bmap_list_t *hp)
480*7917SReza.Sabdar@Sun.COM {
481*7917SReza.Sabdar@Sun.COM 	int i;
482*7917SReza.Sabdar@Sun.COM 
483*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_HASH_SIZE; hp++, i++)
484*7917SReza.Sabdar@Sun.COM 		hash_free(hp);
485*7917SReza.Sabdar@Sun.COM }
486*7917SReza.Sabdar@Sun.COM 
487*7917SReza.Sabdar@Sun.COM 
488*7917SReza.Sabdar@Sun.COM /*
489*7917SReza.Sabdar@Sun.COM  * bm_chunk_repositions
490*7917SReza.Sabdar@Sun.COM  *
491*7917SReza.Sabdar@Sun.COM  * Re-position the chunk in the MRU hash table.
492*7917SReza.Sabdar@Sun.COM  */
493*7917SReza.Sabdar@Sun.COM static void
494*7917SReza.Sabdar@Sun.COM bm_chunk_reposition(bitmap_t *bmp, bmap_list_t *hp, bmap_chunk_t *cp)
495*7917SReza.Sabdar@Sun.COM {
496*7917SReza.Sabdar@Sun.COM 	if (!bmp || !hp || !cp)
497*7917SReza.Sabdar@Sun.COM 		return;
498*7917SReza.Sabdar@Sun.COM 
499*7917SReza.Sabdar@Sun.COM 	if (TAILQ_FIRST(hp) != cp) {
500*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
501*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(hp, cp, c_hash);
502*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
503*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_HEAD(hp, cp, c_hash);
504*7917SReza.Sabdar@Sun.COM 	}
505*7917SReza.Sabdar@Sun.COM }
506*7917SReza.Sabdar@Sun.COM 
507*7917SReza.Sabdar@Sun.COM 
508*7917SReza.Sabdar@Sun.COM /*
509*7917SReza.Sabdar@Sun.COM  * bm_chunk_find
510*7917SReza.Sabdar@Sun.COM  *
511*7917SReza.Sabdar@Sun.COM  * Find and return the chunks which holds the specified bit. Allocate
512*7917SReza.Sabdar@Sun.COM  * the chunk if necessary and re-position it in the hash table lists.
513*7917SReza.Sabdar@Sun.COM  */
514*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
515*7917SReza.Sabdar@Sun.COM bm_chunk_find(bitmap_t *bmp, u_quad_t bn)
516*7917SReza.Sabdar@Sun.COM {
517*7917SReza.Sabdar@Sun.COM 	int h;
518*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
519*7917SReza.Sabdar@Sun.COM 	bmap_list_t *hp;
520*7917SReza.Sabdar@Sun.COM 
521*7917SReza.Sabdar@Sun.COM 	if (!bmp)
522*7917SReza.Sabdar@Sun.COM 		return (NULL);
523*7917SReza.Sabdar@Sun.COM 
524*7917SReza.Sabdar@Sun.COM 	h = HASH(bn);
525*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
526*7917SReza.Sabdar@Sun.COM 	TAILQ_FOREACH(cp, hp, c_hash) {
527*7917SReza.Sabdar@Sun.COM 		if (bn >= cp->c_off && bn < (cp->c_off + cp->c_clen)) {
528*7917SReza.Sabdar@Sun.COM 			bitmap_stats.bs_cache_hit++;
529*7917SReza.Sabdar@Sun.COM 
530*7917SReza.Sabdar@Sun.COM 			bm_chunk_reposition(bmp, hp, cp);
531*7917SReza.Sabdar@Sun.COM 			return (cp);
532*7917SReza.Sabdar@Sun.COM 		}
533*7917SReza.Sabdar@Sun.COM 	}
534*7917SReza.Sabdar@Sun.COM 
535*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_cache_miss++;
536*7917SReza.Sabdar@Sun.COM 
537*7917SReza.Sabdar@Sun.COM 	return (bm_chunk_alloc(bmp, bn));
538*7917SReza.Sabdar@Sun.COM }
539*7917SReza.Sabdar@Sun.COM 
540*7917SReza.Sabdar@Sun.COM 
541*7917SReza.Sabdar@Sun.COM /*
542*7917SReza.Sabdar@Sun.COM  * bmp_setval
543*7917SReza.Sabdar@Sun.COM  *
544*7917SReza.Sabdar@Sun.COM  * Set a range of bits in the bitmap specified by the vector.
545*7917SReza.Sabdar@Sun.COM  */
546*7917SReza.Sabdar@Sun.COM static int
547*7917SReza.Sabdar@Sun.COM bmp_setval(bitmap_t *bmp, bm_iovec_t *vp)
548*7917SReza.Sabdar@Sun.COM {
549*7917SReza.Sabdar@Sun.COM 	int rv;
550*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
551*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
552*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
553*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
554*7917SReza.Sabdar@Sun.COM 
555*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
556*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
557*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
558*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
559*7917SReza.Sabdar@Sun.COM 
560*7917SReza.Sabdar@Sun.COM 	if (*vp->bmv_val) {
561*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set++;
562*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set_bits += vp->bmv_len;
563*7917SReza.Sabdar@Sun.COM 	} else {
564*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset++;
565*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset_bits += vp->bmv_len;
566*7917SReza.Sabdar@Sun.COM 	}
567*7917SReza.Sabdar@Sun.COM 
568*7917SReza.Sabdar@Sun.COM 	do {
569*7917SReza.Sabdar@Sun.COM 		cp = bm_chunk_find(bmp, bn);
570*7917SReza.Sabdar@Sun.COM 		if (!cp)
571*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
572*7917SReza.Sabdar@Sun.COM 
573*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
574*7917SReza.Sabdar@Sun.COM 			rv = bmp_set(cp, bn, vp->bmv_val);
575*7917SReza.Sabdar@Sun.COM 			if (rv != 0)
576*7917SReza.Sabdar@Sun.COM 				return (rv);
577*7917SReza.Sabdar@Sun.COM 		}
578*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
579*7917SReza.Sabdar@Sun.COM 
580*7917SReza.Sabdar@Sun.COM 	return (0);
581*7917SReza.Sabdar@Sun.COM }
582*7917SReza.Sabdar@Sun.COM 
583*7917SReza.Sabdar@Sun.COM 
584*7917SReza.Sabdar@Sun.COM /*
585*7917SReza.Sabdar@Sun.COM  * bmp_getval
586*7917SReza.Sabdar@Sun.COM  *
587*7917SReza.Sabdar@Sun.COM  * Get a range of bits in the bitmap specified by the vector.
588*7917SReza.Sabdar@Sun.COM  */
589*7917SReza.Sabdar@Sun.COM static int
590*7917SReza.Sabdar@Sun.COM bmp_getval(bitmap_t *bmp, bm_iovec_t *vp)
591*7917SReza.Sabdar@Sun.COM {
592*7917SReza.Sabdar@Sun.COM 	uint_t cnt;
593*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
594*7917SReza.Sabdar@Sun.COM 	int rv;
595*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
596*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
597*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
598*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
599*7917SReza.Sabdar@Sun.COM 
600*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
601*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
602*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
603*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
604*7917SReza.Sabdar@Sun.COM 
605*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get++;
606*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get_bits += 1;
607*7917SReza.Sabdar@Sun.COM 
608*7917SReza.Sabdar@Sun.COM 	cnt = 0;
609*7917SReza.Sabdar@Sun.COM 	ip = vp->bmv_val;
610*7917SReza.Sabdar@Sun.COM 	*ip = 0;
611*7917SReza.Sabdar@Sun.COM 	do {
612*7917SReza.Sabdar@Sun.COM 		cp = bm_chunk_find(bmp, bn);
613*7917SReza.Sabdar@Sun.COM 		if (!cp)
614*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
615*7917SReza.Sabdar@Sun.COM 
616*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
617*7917SReza.Sabdar@Sun.COM 			rv = bmp_get(cp, bn);
618*7917SReza.Sabdar@Sun.COM 			if (rv < 0)
619*7917SReza.Sabdar@Sun.COM 				return (rv);
620*7917SReza.Sabdar@Sun.COM 
621*7917SReza.Sabdar@Sun.COM 			*ip |= rv << cnt;
622*7917SReza.Sabdar@Sun.COM 			if (++cnt >= BMAP_BPW) {
623*7917SReza.Sabdar@Sun.COM 				*++ip = 0;
624*7917SReza.Sabdar@Sun.COM 				cnt = 0;
625*7917SReza.Sabdar@Sun.COM 			}
626*7917SReza.Sabdar@Sun.COM 		}
627*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
628*7917SReza.Sabdar@Sun.COM 
629*7917SReza.Sabdar@Sun.COM 	return (0);
630*7917SReza.Sabdar@Sun.COM }
631*7917SReza.Sabdar@Sun.COM 
632*7917SReza.Sabdar@Sun.COM 
633*7917SReza.Sabdar@Sun.COM /*
634*7917SReza.Sabdar@Sun.COM  * hash_init
635*7917SReza.Sabdar@Sun.COM  *
636*7917SReza.Sabdar@Sun.COM  * Initialize the hash table lists head.
637*7917SReza.Sabdar@Sun.COM  */
638*7917SReza.Sabdar@Sun.COM static void
639*7917SReza.Sabdar@Sun.COM hash_init(bmap_list_t *hp)
640*7917SReza.Sabdar@Sun.COM {
641*7917SReza.Sabdar@Sun.COM 	int i;
642*7917SReza.Sabdar@Sun.COM 
643*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_HASH_SIZE; hp++, i++) {
644*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
645*7917SReza.Sabdar@Sun.COM 		TAILQ_INIT(hp);
646*7917SReza.Sabdar@Sun.COM 	}
647*7917SReza.Sabdar@Sun.COM }
648*7917SReza.Sabdar@Sun.COM 
649*7917SReza.Sabdar@Sun.COM 
650*7917SReza.Sabdar@Sun.COM /*
651*7917SReza.Sabdar@Sun.COM  * bm_alloc
652*7917SReza.Sabdar@Sun.COM  *
653*7917SReza.Sabdar@Sun.COM  * Allocate a bit map and return a handle to it.
654*7917SReza.Sabdar@Sun.COM  *
655*7917SReza.Sabdar@Sun.COM  * The hash table list are empty at this point. They are allocated
656*7917SReza.Sabdar@Sun.COM  * on demand.
657*7917SReza.Sabdar@Sun.COM  */
658*7917SReza.Sabdar@Sun.COM int
659*7917SReza.Sabdar@Sun.COM bm_alloc(u_quad_t len, int set)
660*7917SReza.Sabdar@Sun.COM {
661*7917SReza.Sabdar@Sun.COM 	int bmd;
662*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
663*7917SReza.Sabdar@Sun.COM 
664*7917SReza.Sabdar@Sun.COM 	if (len == 0)
665*7917SReza.Sabdar@Sun.COM 		return (-1);
666*7917SReza.Sabdar@Sun.COM 
667*7917SReza.Sabdar@Sun.COM 	bmd = bmd_alloc();
668*7917SReza.Sabdar@Sun.COM 	if (bmd < 0)
669*7917SReza.Sabdar@Sun.COM 		return (bmd);
670*7917SReza.Sabdar@Sun.COM 
671*7917SReza.Sabdar@Sun.COM 	bmp = bmd2bmp(bmd);
672*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_alloc_cnt++;
673*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_alloc_size += len;
674*7917SReza.Sabdar@Sun.COM 
675*7917SReza.Sabdar@Sun.COM 	if (set)
676*7917SReza.Sabdar@Sun.COM 		BMAP_SET_FLAGS(bmp, BMAP_BINIT_ONES);
677*7917SReza.Sabdar@Sun.COM 	else
678*7917SReza.Sabdar@Sun.COM 		BMAP_UNSET_FLAGS(bmp, BMAP_BINIT_ONES);
679*7917SReza.Sabdar@Sun.COM 	bmp->bm_len = len;
680*7917SReza.Sabdar@Sun.COM 	bmp->bm_ccur = 0;
681*7917SReza.Sabdar@Sun.COM 	bmp->bm_cmax = BMAP_CHUNK_MAX;
682*7917SReza.Sabdar@Sun.COM 	hash_init(bmp->bm_hash);
683*7917SReza.Sabdar@Sun.COM 
684*7917SReza.Sabdar@Sun.COM 	return (bmd);
685*7917SReza.Sabdar@Sun.COM }
686*7917SReza.Sabdar@Sun.COM 
687*7917SReza.Sabdar@Sun.COM 
688*7917SReza.Sabdar@Sun.COM /*
689*7917SReza.Sabdar@Sun.COM  * bm_free
690*7917SReza.Sabdar@Sun.COM  *
691*7917SReza.Sabdar@Sun.COM  * Free memory allocated for the bitmap.
692*7917SReza.Sabdar@Sun.COM  */
693*7917SReza.Sabdar@Sun.COM int
694*7917SReza.Sabdar@Sun.COM bm_free(int bmd)
695*7917SReza.Sabdar@Sun.COM {
696*7917SReza.Sabdar@Sun.COM 	int rv;
697*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
698*7917SReza.Sabdar@Sun.COM 
699*7917SReza.Sabdar@Sun.COM 	bmp = bmd2bmp(bmd);
700*7917SReza.Sabdar@Sun.COM 	if (bmp && BMAP_IS_INUSE(bmp)) {
701*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_free_cnt++;
702*7917SReza.Sabdar@Sun.COM 
703*7917SReza.Sabdar@Sun.COM 		bm_chunks_free(bmp->bm_hash);
704*7917SReza.Sabdar@Sun.COM 		bmd_free(bmd);
705*7917SReza.Sabdar@Sun.COM 		rv = 0;
706*7917SReza.Sabdar@Sun.COM 	} else
707*7917SReza.Sabdar@Sun.COM 		rv = -1;
708*7917SReza.Sabdar@Sun.COM 
709*7917SReza.Sabdar@Sun.COM 	return (rv);
710*7917SReza.Sabdar@Sun.COM }
711*7917SReza.Sabdar@Sun.COM 
712*7917SReza.Sabdar@Sun.COM 
713*7917SReza.Sabdar@Sun.COM /*
714*7917SReza.Sabdar@Sun.COM  * bm_getiov
715*7917SReza.Sabdar@Sun.COM  *
716*7917SReza.Sabdar@Sun.COM  * Get bits specified by the array of vectors.
717*7917SReza.Sabdar@Sun.COM  */
718*7917SReza.Sabdar@Sun.COM int
719*7917SReza.Sabdar@Sun.COM bm_getiov(int bmd, bm_io_t *iop)
720*7917SReza.Sabdar@Sun.COM {
721*7917SReza.Sabdar@Sun.COM 	int i;
722*7917SReza.Sabdar@Sun.COM 	int rv;
723*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
724*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
725*7917SReza.Sabdar@Sun.COM 
726*7917SReza.Sabdar@Sun.COM 	if (!iop)
727*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
728*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2bmp(bmd)))
729*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
730*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
731*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
732*7917SReza.Sabdar@Sun.COM 	else {
733*7917SReza.Sabdar@Sun.COM 		rv = 0;
734*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
735*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++) {
736*7917SReza.Sabdar@Sun.COM 			if (!vp)
737*7917SReza.Sabdar@Sun.COM 				return (-EINVAL);
738*7917SReza.Sabdar@Sun.COM 			rv |= bmp_getval(bmp, vp);
739*7917SReza.Sabdar@Sun.COM 		}
740*7917SReza.Sabdar@Sun.COM 	}
741*7917SReza.Sabdar@Sun.COM 
742*7917SReza.Sabdar@Sun.COM 	return (rv);
743*7917SReza.Sabdar@Sun.COM }
744*7917SReza.Sabdar@Sun.COM 
745*7917SReza.Sabdar@Sun.COM 
746*7917SReza.Sabdar@Sun.COM /*
747*7917SReza.Sabdar@Sun.COM  * bm_setiov
748*7917SReza.Sabdar@Sun.COM  *
749*7917SReza.Sabdar@Sun.COM  * Set bits specified by the array of vectors.
750*7917SReza.Sabdar@Sun.COM  */
751*7917SReza.Sabdar@Sun.COM int
752*7917SReza.Sabdar@Sun.COM bm_setiov(int bmd, bm_io_t *iop)
753*7917SReza.Sabdar@Sun.COM {
754*7917SReza.Sabdar@Sun.COM 	int i;
755*7917SReza.Sabdar@Sun.COM 	int rv;
756*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
757*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
758*7917SReza.Sabdar@Sun.COM 
759*7917SReza.Sabdar@Sun.COM 	if (!iop)
760*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
761*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2bmp(bmd)))
762*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
763*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
764*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
765*7917SReza.Sabdar@Sun.COM 	else if (!iop->bmio_iov)
766*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
767*7917SReza.Sabdar@Sun.COM 	else {
768*7917SReza.Sabdar@Sun.COM 		rv = 0;
769*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
770*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++)
771*7917SReza.Sabdar@Sun.COM 			rv |= bmp_setval(bmp, vp);
772*7917SReza.Sabdar@Sun.COM 	}
773*7917SReza.Sabdar@Sun.COM 
774*7917SReza.Sabdar@Sun.COM 	return (rv);
775*7917SReza.Sabdar@Sun.COM }
776*7917SReza.Sabdar@Sun.COM 
777*7917SReza.Sabdar@Sun.COM 
778*7917SReza.Sabdar@Sun.COM /*
779*7917SReza.Sabdar@Sun.COM  * bmd2dbmp
780*7917SReza.Sabdar@Sun.COM  *
781*7917SReza.Sabdar@Sun.COM  * Convert bitmap descriptor to bitmap pointer.
782*7917SReza.Sabdar@Sun.COM  */
783*7917SReza.Sabdar@Sun.COM static dbitmap_t *
784*7917SReza.Sabdar@Sun.COM bmd2dbmp(int bmd)
785*7917SReza.Sabdar@Sun.COM {
786*7917SReza.Sabdar@Sun.COM 	if (bmd < 0 || bmd >= BMAP_MAX)
787*7917SReza.Sabdar@Sun.COM 		return (NULL);
788*7917SReza.Sabdar@Sun.COM 
789*7917SReza.Sabdar@Sun.COM 	return (&dbitmap[bmd]);
790*7917SReza.Sabdar@Sun.COM }
791*7917SReza.Sabdar@Sun.COM 
792*7917SReza.Sabdar@Sun.COM 
793*7917SReza.Sabdar@Sun.COM /*
794*7917SReza.Sabdar@Sun.COM  * dbmp2bmd
795*7917SReza.Sabdar@Sun.COM  *
796*7917SReza.Sabdar@Sun.COM  * Convert bitmap pointer to bitmap descriptor.
797*7917SReza.Sabdar@Sun.COM  */
798*7917SReza.Sabdar@Sun.COM static int
799*7917SReza.Sabdar@Sun.COM dbmp2bmd(dbitmap_t *bmp)
800*7917SReza.Sabdar@Sun.COM {
801*7917SReza.Sabdar@Sun.COM 	int bmd;
802*7917SReza.Sabdar@Sun.COM 
803*7917SReza.Sabdar@Sun.COM 	bmd = bmp - dbitmap;
804*7917SReza.Sabdar@Sun.COM 	if (bmd < 0 || bmd >= BMAP_MAX)
805*7917SReza.Sabdar@Sun.COM 		bmd = -1;
806*7917SReza.Sabdar@Sun.COM 
807*7917SReza.Sabdar@Sun.COM 	return (bmd);
808*7917SReza.Sabdar@Sun.COM }
809*7917SReza.Sabdar@Sun.COM 
810*7917SReza.Sabdar@Sun.COM /*
811*7917SReza.Sabdar@Sun.COM  * dbmd_alloc
812*7917SReza.Sabdar@Sun.COM  *
813*7917SReza.Sabdar@Sun.COM  * Allocate a bitmap descriptor.
814*7917SReza.Sabdar@Sun.COM  * Sets the INUSE flag of the slot.
815*7917SReza.Sabdar@Sun.COM  */
816*7917SReza.Sabdar@Sun.COM static int
817*7917SReza.Sabdar@Sun.COM dbmd_alloc(void)
818*7917SReza.Sabdar@Sun.COM {
819*7917SReza.Sabdar@Sun.COM 	int i;
820*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
821*7917SReza.Sabdar@Sun.COM 
822*7917SReza.Sabdar@Sun.COM 	bmp = dbitmap;
823*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_MAX; bmp++, i++)
824*7917SReza.Sabdar@Sun.COM 		if (!BMAP_IS_INUSE(bmp)) {
825*7917SReza.Sabdar@Sun.COM 			BMAP_SET_FLAGS(bmp, BMAP_INUSE);
826*7917SReza.Sabdar@Sun.COM 			return (i);
827*7917SReza.Sabdar@Sun.COM 		}
828*7917SReza.Sabdar@Sun.COM 
829*7917SReza.Sabdar@Sun.COM 	return (-1);
830*7917SReza.Sabdar@Sun.COM }
831*7917SReza.Sabdar@Sun.COM 
832*7917SReza.Sabdar@Sun.COM 
833*7917SReza.Sabdar@Sun.COM /*
834*7917SReza.Sabdar@Sun.COM  * dbmd_free
835*7917SReza.Sabdar@Sun.COM  *
836*7917SReza.Sabdar@Sun.COM  * Free a bitmap descriptor.
837*7917SReza.Sabdar@Sun.COM  * Clears the INUSE flag of the slot.
838*7917SReza.Sabdar@Sun.COM  */
839*7917SReza.Sabdar@Sun.COM static void
840*7917SReza.Sabdar@Sun.COM dbmd_free(int bmd)
841*7917SReza.Sabdar@Sun.COM {
842*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
843*7917SReza.Sabdar@Sun.COM 
844*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
845*7917SReza.Sabdar@Sun.COM 	if (bmp)
846*7917SReza.Sabdar@Sun.COM 		BMAP_UNSET_FLAGS(bmp, BMAP_INUSE);
847*7917SReza.Sabdar@Sun.COM }
848*7917SReza.Sabdar@Sun.COM 
849*7917SReza.Sabdar@Sun.COM 
850*7917SReza.Sabdar@Sun.COM /*
851*7917SReza.Sabdar@Sun.COM  * dbmp_set
852*7917SReza.Sabdar@Sun.COM  *
853*7917SReza.Sabdar@Sun.COM  * Generic function to set bit in a chunk.  This can
854*7917SReza.Sabdar@Sun.COM  * set or unset the specified bit.
855*7917SReza.Sabdar@Sun.COM  */
856*7917SReza.Sabdar@Sun.COM static inline int
857*7917SReza.Sabdar@Sun.COM dbmp_set(dbmap_chunk_t *cp, u_quad_t bn, uint_t *vp)
858*7917SReza.Sabdar@Sun.COM {
859*7917SReza.Sabdar@Sun.COM 	int rv;
860*7917SReza.Sabdar@Sun.COM 	uint_t mask;
861*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
862*7917SReza.Sabdar@Sun.COM 	uint_t v;
863*7917SReza.Sabdar@Sun.COM 
864*7917SReza.Sabdar@Sun.COM 	bn -= cp->c_off;
865*7917SReza.Sabdar@Sun.COM 	if (bn < cp->c_clen) {
866*7917SReza.Sabdar@Sun.COM 		mask = 1 <<(bn & BMAP_BPW_MASK);
867*7917SReza.Sabdar@Sun.COM 		ip = &cp->c_bmp[bn >> BMAP_BPW_SHIFT];
868*7917SReza.Sabdar@Sun.COM 		v = (*vp <<(bn & BMAP_BPW_MASK)) & mask;
869*7917SReza.Sabdar@Sun.COM 		*ip = (*ip & ~mask) | v;
870*7917SReza.Sabdar@Sun.COM 		BMAP_CSET_DIRTY(cp);
871*7917SReza.Sabdar@Sun.COM 		rv = 0;
872*7917SReza.Sabdar@Sun.COM 	} else
873*7917SReza.Sabdar@Sun.COM 		rv = -ERANGE;
874*7917SReza.Sabdar@Sun.COM 
875*7917SReza.Sabdar@Sun.COM 	return (rv);
876*7917SReza.Sabdar@Sun.COM }
877*7917SReza.Sabdar@Sun.COM 
878*7917SReza.Sabdar@Sun.COM 
879*7917SReza.Sabdar@Sun.COM /*
880*7917SReza.Sabdar@Sun.COM  * dbmp_getlen
881*7917SReza.Sabdar@Sun.COM  *
882*7917SReza.Sabdar@Sun.COM  * Get length of the bitmap.
883*7917SReza.Sabdar@Sun.COM  */
884*7917SReza.Sabdar@Sun.COM static u_quad_t
885*7917SReza.Sabdar@Sun.COM dbmp_getlen(dbitmap_t *bmp)
886*7917SReza.Sabdar@Sun.COM {
887*7917SReza.Sabdar@Sun.COM 	return (bmp ? bmp->bm_len : 0LL);
888*7917SReza.Sabdar@Sun.COM }
889*7917SReza.Sabdar@Sun.COM 
890*7917SReza.Sabdar@Sun.COM 
891*7917SReza.Sabdar@Sun.COM /*
892*7917SReza.Sabdar@Sun.COM  * dbmp_get
893*7917SReza.Sabdar@Sun.COM  *
894*7917SReza.Sabdar@Sun.COM  * Generic function to get bit in a chunk.
895*7917SReza.Sabdar@Sun.COM  */
896*7917SReza.Sabdar@Sun.COM static inline int
897*7917SReza.Sabdar@Sun.COM dbmp_get(dbmap_chunk_t *cp, u_quad_t bn)
898*7917SReza.Sabdar@Sun.COM {
899*7917SReza.Sabdar@Sun.COM 	int rv;
900*7917SReza.Sabdar@Sun.COM 	uint_t bit;
901*7917SReza.Sabdar@Sun.COM 
902*7917SReza.Sabdar@Sun.COM 	bn -= cp->c_off;
903*7917SReza.Sabdar@Sun.COM 	if (bn < cp->c_clen) {
904*7917SReza.Sabdar@Sun.COM 		bit = 1 <<(bn & BMAP_BPW_MASK);
905*7917SReza.Sabdar@Sun.COM 		rv = (cp->c_bmp[bn >> BMAP_BPW_SHIFT] & bit) != 0;
906*7917SReza.Sabdar@Sun.COM 	} else
907*7917SReza.Sabdar@Sun.COM 		rv = -ERANGE;
908*7917SReza.Sabdar@Sun.COM 
909*7917SReza.Sabdar@Sun.COM 	return (rv);
910*7917SReza.Sabdar@Sun.COM }
911*7917SReza.Sabdar@Sun.COM 
912*7917SReza.Sabdar@Sun.COM 
913*7917SReza.Sabdar@Sun.COM /*
914*7917SReza.Sabdar@Sun.COM  * dbm_chunk_seek
915*7917SReza.Sabdar@Sun.COM  *
916*7917SReza.Sabdar@Sun.COM  * Seek in the file where the chunk is saved or should be saved.
917*7917SReza.Sabdar@Sun.COM  */
918*7917SReza.Sabdar@Sun.COM static int
919*7917SReza.Sabdar@Sun.COM dbm_chunk_seek(dbitmap_t *bmp, u_quad_t bn)
920*7917SReza.Sabdar@Sun.COM {
921*7917SReza.Sabdar@Sun.COM 	int rv;
922*7917SReza.Sabdar@Sun.COM 	off_t off;
923*7917SReza.Sabdar@Sun.COM 
924*7917SReza.Sabdar@Sun.COM 	if (!bmp)
925*7917SReza.Sabdar@Sun.COM 		rv = -1;
926*7917SReza.Sabdar@Sun.COM 	else {
927*7917SReza.Sabdar@Sun.COM 		off = BMAP_CHUNK_NO(bn) * BMAP_CHUNK_BYTES;
928*7917SReza.Sabdar@Sun.COM 		rv = (lseek(bmp->bm_fd, off, SEEK_SET) != off) ? -1 : 0;
929*7917SReza.Sabdar@Sun.COM 	}
930*7917SReza.Sabdar@Sun.COM 
931*7917SReza.Sabdar@Sun.COM 	return (rv);
932*7917SReza.Sabdar@Sun.COM }
933*7917SReza.Sabdar@Sun.COM 
934*7917SReza.Sabdar@Sun.COM 
935*7917SReza.Sabdar@Sun.COM /*
936*7917SReza.Sabdar@Sun.COM  * dbm_chunk_flush
937*7917SReza.Sabdar@Sun.COM  *
938*7917SReza.Sabdar@Sun.COM  * Save a chunk to file.
939*7917SReza.Sabdar@Sun.COM  */
940*7917SReza.Sabdar@Sun.COM static int
941*7917SReza.Sabdar@Sun.COM dbm_chunk_flush(dbitmap_t *bmp, dbmap_chunk_t *cp)
942*7917SReza.Sabdar@Sun.COM {
943*7917SReza.Sabdar@Sun.COM 	int rv;
944*7917SReza.Sabdar@Sun.COM 
945*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_flush++;
946*7917SReza.Sabdar@Sun.COM 	if (!bmp || !cp)
947*7917SReza.Sabdar@Sun.COM 		rv = -1;
948*7917SReza.Sabdar@Sun.COM 	else if (dbm_chunk_seek(bmp, cp->c_off) != 0)
949*7917SReza.Sabdar@Sun.COM 		rv = -1;
950*7917SReza.Sabdar@Sun.COM 	else if (write(bmp->bm_fd, cp->c_bmp, cp->c_mlen) != cp->c_mlen)
951*7917SReza.Sabdar@Sun.COM 		rv = -1;
952*7917SReza.Sabdar@Sun.COM 	else
953*7917SReza.Sabdar@Sun.COM 		rv = 0;
954*7917SReza.Sabdar@Sun.COM 
955*7917SReza.Sabdar@Sun.COM 	return (rv);
956*7917SReza.Sabdar@Sun.COM }
957*7917SReza.Sabdar@Sun.COM 
958*7917SReza.Sabdar@Sun.COM 
959*7917SReza.Sabdar@Sun.COM /*
960*7917SReza.Sabdar@Sun.COM  * dbm_chunk_load
961*7917SReza.Sabdar@Sun.COM  *
962*7917SReza.Sabdar@Sun.COM  * Load a chunk from a file.  If the chunk is a new one,
963*7917SReza.Sabdar@Sun.COM  * instead of reading from the disk, the memory for the
964*7917SReza.Sabdar@Sun.COM  * chunk is set to either all zeros or to all ones.
965*7917SReza.Sabdar@Sun.COM  * Otherwise, if the chunk is not a new one, it's read
966*7917SReza.Sabdar@Sun.COM  * from the disk.
967*7917SReza.Sabdar@Sun.COM  *
968*7917SReza.Sabdar@Sun.COM  * The new chunk is positioned in the LRU and hash table
969*7917SReza.Sabdar@Sun.COM  * after its data is ready.
970*7917SReza.Sabdar@Sun.COM  */
971*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
972*7917SReza.Sabdar@Sun.COM dbm_chunk_load(dbitmap_t *bmp, dbmap_chunk_t *cp, u_quad_t bn, int new)
973*7917SReza.Sabdar@Sun.COM {
974*7917SReza.Sabdar@Sun.COM 	int h;
975*7917SReza.Sabdar@Sun.COM 	u_quad_t off, l;
976*7917SReza.Sabdar@Sun.COM 	uint_t cl, ml;
977*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *hp;
978*7917SReza.Sabdar@Sun.COM 
979*7917SReza.Sabdar@Sun.COM 	off = BMAP_CHUNK_OFF(bn);
980*7917SReza.Sabdar@Sun.COM 	l = bmp->bm_len - off;
981*7917SReza.Sabdar@Sun.COM 	if (l >= BMAP_CHUNK_BITS) {
982*7917SReza.Sabdar@Sun.COM 		cl = BMAP_CHUNK_BITS;
983*7917SReza.Sabdar@Sun.COM 		ml = BMAP_CHUNK_BYTES;
984*7917SReza.Sabdar@Sun.COM 	} else {
985*7917SReza.Sabdar@Sun.COM 		cl = l;
986*7917SReza.Sabdar@Sun.COM 		ml = MEM_LEN(l);
987*7917SReza.Sabdar@Sun.COM 	}
988*7917SReza.Sabdar@Sun.COM 
989*7917SReza.Sabdar@Sun.COM 	if (new == BMAP_NEW_CHUNK) {
990*7917SReza.Sabdar@Sun.COM 		if (BMAP_IS_INIT_ONES(bmp))
991*7917SReza.Sabdar@Sun.COM 			(void) memset(cp->c_bmp, 0xff, ml);
992*7917SReza.Sabdar@Sun.COM 		else
993*7917SReza.Sabdar@Sun.COM 			(void) memset(cp->c_bmp, 0x00, ml);
994*7917SReza.Sabdar@Sun.COM 	} else { /* BMAP_OLD_CHUNK */
995*7917SReza.Sabdar@Sun.COM 		if (dbm_chunk_seek(bmp, bn) != 0)
996*7917SReza.Sabdar@Sun.COM 			cp = NULL;
997*7917SReza.Sabdar@Sun.COM 		else if (read(bmp->bm_fd, cp->c_bmp, ml) != ml)
998*7917SReza.Sabdar@Sun.COM 			cp = NULL;
999*7917SReza.Sabdar@Sun.COM 	}
1000*7917SReza.Sabdar@Sun.COM 
1001*7917SReza.Sabdar@Sun.COM 	if (cp) {
1002*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
1003*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_TAIL(&bmp->bm_lru, cp, c_lru);
1004*7917SReza.Sabdar@Sun.COM 		h = HASH(bn);
1005*7917SReza.Sabdar@Sun.COM 		hp = &bmp->bm_hash[h];
1006*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
1007*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_HEAD(hp, cp, c_hash);
1008*7917SReza.Sabdar@Sun.COM 		cp->c_flags = 0;
1009*7917SReza.Sabdar@Sun.COM 		cp->c_off = off;
1010*7917SReza.Sabdar@Sun.COM 		cp->c_clen = cl;
1011*7917SReza.Sabdar@Sun.COM 		cp->c_mlen = ml;
1012*7917SReza.Sabdar@Sun.COM 	}
1013*7917SReza.Sabdar@Sun.COM 
1014*7917SReza.Sabdar@Sun.COM 	return (cp);
1015*7917SReza.Sabdar@Sun.COM }
1016*7917SReza.Sabdar@Sun.COM 
1017*7917SReza.Sabdar@Sun.COM 
1018*7917SReza.Sabdar@Sun.COM /*
1019*7917SReza.Sabdar@Sun.COM  * dbm_chunk_new
1020*7917SReza.Sabdar@Sun.COM  *
1021*7917SReza.Sabdar@Sun.COM  * Create a new chunk and keep track of memory used.
1022*7917SReza.Sabdar@Sun.COM  */
1023*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
1024*7917SReza.Sabdar@Sun.COM dbm_chunk_new(dbitmap_t *bmp, u_quad_t bn)
1025*7917SReza.Sabdar@Sun.COM {
1026*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1027*7917SReza.Sabdar@Sun.COM 
1028*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_new++;
1029*7917SReza.Sabdar@Sun.COM 	cp = ndmp_malloc(sizeof (dbmap_chunk_t));
1030*7917SReza.Sabdar@Sun.COM 	if (cp) {
1031*7917SReza.Sabdar@Sun.COM 		cp->c_bmp = ndmp_malloc(sizeof (uint_t) * BMAP_CHUNK_WORDS);
1032*7917SReza.Sabdar@Sun.COM 		if (!cp->c_bmp) {
1033*7917SReza.Sabdar@Sun.COM 			free(cp);
1034*7917SReza.Sabdar@Sun.COM 			cp = NULL;
1035*7917SReza.Sabdar@Sun.COM 		} else if (!dbm_chunk_load(bmp, cp, bn, BMAP_NEW_CHUNK)) {
1036*7917SReza.Sabdar@Sun.COM 			free(cp->c_bmp);
1037*7917SReza.Sabdar@Sun.COM 			free(cp);
1038*7917SReza.Sabdar@Sun.COM 			cp = NULL;
1039*7917SReza.Sabdar@Sun.COM 		} else
1040*7917SReza.Sabdar@Sun.COM 			bmp->bm_ccur++;
1041*7917SReza.Sabdar@Sun.COM 	}
1042*7917SReza.Sabdar@Sun.COM 
1043*7917SReza.Sabdar@Sun.COM 	return (cp);
1044*7917SReza.Sabdar@Sun.COM }
1045*7917SReza.Sabdar@Sun.COM 
1046*7917SReza.Sabdar@Sun.COM 
1047*7917SReza.Sabdar@Sun.COM /*
1048*7917SReza.Sabdar@Sun.COM  * dbm_chunk_alloc
1049*7917SReza.Sabdar@Sun.COM  *
1050*7917SReza.Sabdar@Sun.COM  * Allocate a chunk and return it.  If the cache for the
1051*7917SReza.Sabdar@Sun.COM  * chunks is not fully used, a new chunk is created.
1052*7917SReza.Sabdar@Sun.COM  * Otherwise, the first chunk from the LRU list is reclaimed,
1053*7917SReza.Sabdar@Sun.COM  * loaded and returned.
1054*7917SReza.Sabdar@Sun.COM  */
1055*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
1056*7917SReza.Sabdar@Sun.COM dbm_chunk_alloc(dbitmap_t *bmp, u_quad_t bn)
1057*7917SReza.Sabdar@Sun.COM {
1058*7917SReza.Sabdar@Sun.COM 	int h;
1059*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *hp;
1060*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1061*7917SReza.Sabdar@Sun.COM 
1062*7917SReza.Sabdar@Sun.COM 	if (bmp->bm_ccur < bmp->bm_cmax)
1063*7917SReza.Sabdar@Sun.COM 		return (dbm_chunk_new(bmp, bn));
1064*7917SReza.Sabdar@Sun.COM 
1065*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_reclaim++;
1066*7917SReza.Sabdar@Sun.COM 
1067*7917SReza.Sabdar@Sun.COM 	cp = TAILQ_FIRST(&bmp->bm_lru);
1068*7917SReza.Sabdar@Sun.COM 	if (BMAP_CIS_DIRTY(cp))
1069*7917SReza.Sabdar@Sun.COM 		(void) dbm_chunk_flush(bmp, cp);
1070*7917SReza.Sabdar@Sun.COM 
1071*7917SReza.Sabdar@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
1072*7917SReza.Sabdar@Sun.COM 	TAILQ_REMOVE(&bmp->bm_lru, cp, c_lru);
1073*7917SReza.Sabdar@Sun.COM 	h = HASH(cp->c_off);
1074*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
1075*7917SReza.Sabdar@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
1076*7917SReza.Sabdar@Sun.COM 	TAILQ_REMOVE(hp, cp, c_hash);
1077*7917SReza.Sabdar@Sun.COM 	return (dbm_chunk_load(bmp, cp, bn, BMAP_OLD_CHUNK));
1078*7917SReza.Sabdar@Sun.COM }
1079*7917SReza.Sabdar@Sun.COM 
1080*7917SReza.Sabdar@Sun.COM 
1081*7917SReza.Sabdar@Sun.COM /*
1082*7917SReza.Sabdar@Sun.COM  * dbm_chunks_free
1083*7917SReza.Sabdar@Sun.COM  *
1084*7917SReza.Sabdar@Sun.COM  * Release the memory allocated for the chunks.
1085*7917SReza.Sabdar@Sun.COM  */
1086*7917SReza.Sabdar@Sun.COM static void
1087*7917SReza.Sabdar@Sun.COM dbm_chunks_free(dbitmap_t *bmp)
1088*7917SReza.Sabdar@Sun.COM {
1089*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *headp;
1090*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1091*7917SReza.Sabdar@Sun.COM 
1092*7917SReza.Sabdar@Sun.COM 	if (!bmp)
1093*7917SReza.Sabdar@Sun.COM 		return;
1094*7917SReza.Sabdar@Sun.COM 
1095*7917SReza.Sabdar@Sun.COM 	headp = &bmp->bm_lru;
1096*7917SReza.Sabdar@Sun.COM 	if (!headp)
1097*7917SReza.Sabdar@Sun.COM 		return;
1098*7917SReza.Sabdar@Sun.COM 
1099*7917SReza.Sabdar@Sun.COM 	while (!TAILQ_EMPTY(headp)) {
1100*7917SReza.Sabdar@Sun.COM 		cp = TAILQ_FIRST(headp);
1101*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
1102*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(headp, cp, c_lru);
1103*7917SReza.Sabdar@Sun.COM 		free(cp->c_bmp);
1104*7917SReza.Sabdar@Sun.COM 		free(cp);
1105*7917SReza.Sabdar@Sun.COM 	}
1106*7917SReza.Sabdar@Sun.COM }
1107*7917SReza.Sabdar@Sun.COM 
1108*7917SReza.Sabdar@Sun.COM 
1109*7917SReza.Sabdar@Sun.COM /*
1110*7917SReza.Sabdar@Sun.COM  * dbm_chunk_reposition
1111*7917SReza.Sabdar@Sun.COM  *
1112*7917SReza.Sabdar@Sun.COM  * Re-position the chunk in the LRU and the hash table.
1113*7917SReza.Sabdar@Sun.COM  */
1114*7917SReza.Sabdar@Sun.COM static void
1115*7917SReza.Sabdar@Sun.COM dbm_chunk_reposition(dbitmap_t *bmp, dbmap_list_t *hp, dbmap_chunk_t *cp)
1116*7917SReza.Sabdar@Sun.COM {
1117*7917SReza.Sabdar@Sun.COM 	if (bmp && hp && cp) {
1118*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
1119*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(&bmp->bm_lru, cp, c_lru);
1120*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
1121*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_TAIL(&bmp->bm_lru, cp, c_lru);
1122*7917SReza.Sabdar@Sun.COM 		if (TAILQ_FIRST(hp) != cp) {
1123*7917SReza.Sabdar@Sun.COM 			/* LINTED: E_CONSTANT_CONDITION */
1124*7917SReza.Sabdar@Sun.COM 			TAILQ_REMOVE(hp, cp, c_hash);
1125*7917SReza.Sabdar@Sun.COM 			/* LINTED: E_CONSTANT_CONDITION */
1126*7917SReza.Sabdar@Sun.COM 			TAILQ_INSERT_HEAD(hp, cp, c_hash);
1127*7917SReza.Sabdar@Sun.COM 		}
1128*7917SReza.Sabdar@Sun.COM 	}
1129*7917SReza.Sabdar@Sun.COM }
1130*7917SReza.Sabdar@Sun.COM 
1131*7917SReza.Sabdar@Sun.COM 
1132*7917SReza.Sabdar@Sun.COM /*
1133*7917SReza.Sabdar@Sun.COM  * dbm_chunk_find
1134*7917SReza.Sabdar@Sun.COM  *
1135*7917SReza.Sabdar@Sun.COM  * Find and return the chunks which holds the specified bit.
1136*7917SReza.Sabdar@Sun.COM  * Allocate the chunk if necessary and re-position it in the
1137*7917SReza.Sabdar@Sun.COM  * LRU and hash table lists.
1138*7917SReza.Sabdar@Sun.COM  */
1139*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
1140*7917SReza.Sabdar@Sun.COM dbm_chunk_find(dbitmap_t *bmp, u_quad_t bn)
1141*7917SReza.Sabdar@Sun.COM {
1142*7917SReza.Sabdar@Sun.COM 	int h;
1143*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1144*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *hp;
1145*7917SReza.Sabdar@Sun.COM 
1146*7917SReza.Sabdar@Sun.COM 	if (!bmp)
1147*7917SReza.Sabdar@Sun.COM 		return (NULL);
1148*7917SReza.Sabdar@Sun.COM 
1149*7917SReza.Sabdar@Sun.COM 	h = HASH(bn);
1150*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
1151*7917SReza.Sabdar@Sun.COM 	TAILQ_FOREACH(cp, hp, c_hash) {
1152*7917SReza.Sabdar@Sun.COM 		if (bn >= cp->c_off && bn < (cp->c_off + cp->c_clen)) {
1153*7917SReza.Sabdar@Sun.COM 			bitmap_stats.bs_cache_hit++;
1154*7917SReza.Sabdar@Sun.COM 
1155*7917SReza.Sabdar@Sun.COM 			dbm_chunk_reposition(bmp, hp, cp);
1156*7917SReza.Sabdar@Sun.COM 			return (cp);
1157*7917SReza.Sabdar@Sun.COM 		}
1158*7917SReza.Sabdar@Sun.COM 	}
1159*7917SReza.Sabdar@Sun.COM 
1160*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_cache_miss++;
1161*7917SReza.Sabdar@Sun.COM 
1162*7917SReza.Sabdar@Sun.COM 	return (dbm_chunk_alloc(bmp, bn));
1163*7917SReza.Sabdar@Sun.COM }
1164*7917SReza.Sabdar@Sun.COM 
1165*7917SReza.Sabdar@Sun.COM 
1166*7917SReza.Sabdar@Sun.COM /*
1167*7917SReza.Sabdar@Sun.COM  * dbmp_setval
1168*7917SReza.Sabdar@Sun.COM  *
1169*7917SReza.Sabdar@Sun.COM  * Set a range of bits in the bitmap specified by the
1170*7917SReza.Sabdar@Sun.COM  * vector.
1171*7917SReza.Sabdar@Sun.COM  */
1172*7917SReza.Sabdar@Sun.COM static int
1173*7917SReza.Sabdar@Sun.COM dbmp_setval(dbitmap_t *bmp, bm_iovec_t *vp)
1174*7917SReza.Sabdar@Sun.COM {
1175*7917SReza.Sabdar@Sun.COM 	int rv;
1176*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
1177*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
1178*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
1179*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1180*7917SReza.Sabdar@Sun.COM 
1181*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
1182*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
1183*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
1184*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
1185*7917SReza.Sabdar@Sun.COM 
1186*7917SReza.Sabdar@Sun.COM 	if (*vp->bmv_val) {
1187*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set++;
1188*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set_bits += vp->bmv_len;
1189*7917SReza.Sabdar@Sun.COM 	} else {
1190*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset++;
1191*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset_bits += vp->bmv_len;
1192*7917SReza.Sabdar@Sun.COM 	}
1193*7917SReza.Sabdar@Sun.COM 
1194*7917SReza.Sabdar@Sun.COM 	do {
1195*7917SReza.Sabdar@Sun.COM 		cp = dbm_chunk_find(bmp, bn);
1196*7917SReza.Sabdar@Sun.COM 		if (!cp)
1197*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
1198*7917SReza.Sabdar@Sun.COM 
1199*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
1200*7917SReza.Sabdar@Sun.COM 			rv = dbmp_set(cp, bn, vp->bmv_val);
1201*7917SReza.Sabdar@Sun.COM 			if (rv != 0)
1202*7917SReza.Sabdar@Sun.COM 				return (rv);
1203*7917SReza.Sabdar@Sun.COM 		}
1204*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
1205*7917SReza.Sabdar@Sun.COM 
1206*7917SReza.Sabdar@Sun.COM 	return (0);
1207*7917SReza.Sabdar@Sun.COM }
1208*7917SReza.Sabdar@Sun.COM 
1209*7917SReza.Sabdar@Sun.COM 
1210*7917SReza.Sabdar@Sun.COM /*
1211*7917SReza.Sabdar@Sun.COM  * dbmp_getval
1212*7917SReza.Sabdar@Sun.COM  *
1213*7917SReza.Sabdar@Sun.COM  * Get a range of bits in the bitmap specified by the
1214*7917SReza.Sabdar@Sun.COM  * vector.
1215*7917SReza.Sabdar@Sun.COM  */
1216*7917SReza.Sabdar@Sun.COM static int
1217*7917SReza.Sabdar@Sun.COM dbmp_getval(dbitmap_t *bmp, bm_iovec_t *vp)
1218*7917SReza.Sabdar@Sun.COM {
1219*7917SReza.Sabdar@Sun.COM 	uint_t cnt;
1220*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
1221*7917SReza.Sabdar@Sun.COM 	int rv;
1222*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
1223*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
1224*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
1225*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1226*7917SReza.Sabdar@Sun.COM 
1227*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
1228*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
1229*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
1230*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
1231*7917SReza.Sabdar@Sun.COM 
1232*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get++;
1233*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get_bits += 1;
1234*7917SReza.Sabdar@Sun.COM 
1235*7917SReza.Sabdar@Sun.COM 	cnt = 0;
1236*7917SReza.Sabdar@Sun.COM 	ip = vp->bmv_val;
1237*7917SReza.Sabdar@Sun.COM 	*ip = 0;
1238*7917SReza.Sabdar@Sun.COM 	do {
1239*7917SReza.Sabdar@Sun.COM 		cp = dbm_chunk_find(bmp, bn);
1240*7917SReza.Sabdar@Sun.COM 		if (!cp)
1241*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
1242*7917SReza.Sabdar@Sun.COM 
1243*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
1244*7917SReza.Sabdar@Sun.COM 			rv = dbmp_get(cp, bn);
1245*7917SReza.Sabdar@Sun.COM 			if (rv < 0)
1246*7917SReza.Sabdar@Sun.COM 				return (rv);
1247*7917SReza.Sabdar@Sun.COM 
1248*7917SReza.Sabdar@Sun.COM 			*ip |= rv << cnt;
1249*7917SReza.Sabdar@Sun.COM 			if (++cnt >= BMAP_BPW) {
1250*7917SReza.Sabdar@Sun.COM 				*++ip = 0;
1251*7917SReza.Sabdar@Sun.COM 				cnt = 0;
1252*7917SReza.Sabdar@Sun.COM 			}
1253*7917SReza.Sabdar@Sun.COM 		}
1254*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
1255*7917SReza.Sabdar@Sun.COM 
1256*7917SReza.Sabdar@Sun.COM 	return (0);
1257*7917SReza.Sabdar@Sun.COM }
1258*7917SReza.Sabdar@Sun.COM 
1259*7917SReza.Sabdar@Sun.COM 
1260*7917SReza.Sabdar@Sun.COM /*
1261*7917SReza.Sabdar@Sun.COM  * dbyte_apply_ifset
1262*7917SReza.Sabdar@Sun.COM  *
1263*7917SReza.Sabdar@Sun.COM  * Apply the function on the set bits of the specified word.
1264*7917SReza.Sabdar@Sun.COM  */
1265*7917SReza.Sabdar@Sun.COM static int
1266*7917SReza.Sabdar@Sun.COM dbyte_apply_ifset(dbitmap_t *bmp, u_quad_t off, uint_t b, int(*fp)(),
1267*7917SReza.Sabdar@Sun.COM     void *arg)
1268*7917SReza.Sabdar@Sun.COM {
1269*7917SReza.Sabdar@Sun.COM 	int bmd;
1270*7917SReza.Sabdar@Sun.COM 	int rv;
1271*7917SReza.Sabdar@Sun.COM 	u_quad_t l;
1272*7917SReza.Sabdar@Sun.COM 
1273*7917SReza.Sabdar@Sun.COM 	rv = 0;
1274*7917SReza.Sabdar@Sun.COM 	l = dbmp_getlen(bmp);
1275*7917SReza.Sabdar@Sun.COM 	bmd = dbmp2bmd(bmp);
1276*7917SReza.Sabdar@Sun.COM 	for (; b && off < l; off++) {
1277*7917SReza.Sabdar@Sun.COM 		if (b & 1) {
1278*7917SReza.Sabdar@Sun.COM 			bitmap_stats.bs_set_applied++;
1279*7917SReza.Sabdar@Sun.COM 
1280*7917SReza.Sabdar@Sun.COM 			if ((rv = (*fp)(bmd, off, arg)))
1281*7917SReza.Sabdar@Sun.COM 				break;
1282*7917SReza.Sabdar@Sun.COM 		}
1283*7917SReza.Sabdar@Sun.COM 		b >>= 1;
1284*7917SReza.Sabdar@Sun.COM 	}
1285*7917SReza.Sabdar@Sun.COM 
1286*7917SReza.Sabdar@Sun.COM 	return (rv);
1287*7917SReza.Sabdar@Sun.COM }
1288*7917SReza.Sabdar@Sun.COM 
1289*7917SReza.Sabdar@Sun.COM 
1290*7917SReza.Sabdar@Sun.COM /*
1291*7917SReza.Sabdar@Sun.COM  * dbm_chunk_apply_ifset
1292*7917SReza.Sabdar@Sun.COM  *
1293*7917SReza.Sabdar@Sun.COM  * Apply the function on the set bits of the specified chunk.
1294*7917SReza.Sabdar@Sun.COM  */
1295*7917SReza.Sabdar@Sun.COM static int
1296*7917SReza.Sabdar@Sun.COM dbm_chunk_apply_ifset(dbitmap_t *bmp, dbmap_chunk_t *cp, int(*fp)(),
1297*7917SReza.Sabdar@Sun.COM     void *arg)
1298*7917SReza.Sabdar@Sun.COM {
1299*7917SReza.Sabdar@Sun.COM 	int rv;
1300*7917SReza.Sabdar@Sun.COM 	uint_t *bp;
1301*7917SReza.Sabdar@Sun.COM 	uint_t i, m;
1302*7917SReza.Sabdar@Sun.COM 	u_quad_t q;
1303*7917SReza.Sabdar@Sun.COM 
1304*7917SReza.Sabdar@Sun.COM 	rv = 0;
1305*7917SReza.Sabdar@Sun.COM 	bp = cp->c_bmp;
1306*7917SReza.Sabdar@Sun.COM 	q = cp->c_off;
1307*7917SReza.Sabdar@Sun.COM 	m = cp->c_mlen / BMAP_WSIZE;
1308*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < m; q += BMAP_BPW, bp++, i++)
1309*7917SReza.Sabdar@Sun.COM 		if (*bp) {
1310*7917SReza.Sabdar@Sun.COM 			rv = dbyte_apply_ifset(bmp, q, *bp, fp, arg);
1311*7917SReza.Sabdar@Sun.COM 			if (rv != 0)
1312*7917SReza.Sabdar@Sun.COM 				break;
1313*7917SReza.Sabdar@Sun.COM 		}
1314*7917SReza.Sabdar@Sun.COM 
1315*7917SReza.Sabdar@Sun.COM 	return (rv);
1316*7917SReza.Sabdar@Sun.COM }
1317*7917SReza.Sabdar@Sun.COM 
1318*7917SReza.Sabdar@Sun.COM 
1319*7917SReza.Sabdar@Sun.COM /*
1320*7917SReza.Sabdar@Sun.COM  * swfile_trunc
1321*7917SReza.Sabdar@Sun.COM  *
1322*7917SReza.Sabdar@Sun.COM  * Truncate the rest of the swap file.
1323*7917SReza.Sabdar@Sun.COM  */
1324*7917SReza.Sabdar@Sun.COM static int
1325*7917SReza.Sabdar@Sun.COM swfile_trunc(int fd)
1326*7917SReza.Sabdar@Sun.COM {
1327*7917SReza.Sabdar@Sun.COM 	int rv;
1328*7917SReza.Sabdar@Sun.COM 	off_t off;
1329*7917SReza.Sabdar@Sun.COM 
1330*7917SReza.Sabdar@Sun.COM 	/*
1331*7917SReza.Sabdar@Sun.COM 	 * Get the current offset and truncate whatever is
1332*7917SReza.Sabdar@Sun.COM 	 * after this point.
1333*7917SReza.Sabdar@Sun.COM 	 */
1334*7917SReza.Sabdar@Sun.COM 	rv = 0;
1335*7917SReza.Sabdar@Sun.COM 	if ((off = lseek(fd, 0, SEEK_CUR)) < 0)
1336*7917SReza.Sabdar@Sun.COM 		rv = -1;
1337*7917SReza.Sabdar@Sun.COM 	else if (ftruncate(fd, off) != 0)
1338*7917SReza.Sabdar@Sun.COM 		rv = -1;
1339*7917SReza.Sabdar@Sun.COM 
1340*7917SReza.Sabdar@Sun.COM 	return (rv);
1341*7917SReza.Sabdar@Sun.COM }
1342*7917SReza.Sabdar@Sun.COM 
1343*7917SReza.Sabdar@Sun.COM 
1344*7917SReza.Sabdar@Sun.COM /*
1345*7917SReza.Sabdar@Sun.COM  * swfile_init
1346*7917SReza.Sabdar@Sun.COM  *
1347*7917SReza.Sabdar@Sun.COM  * Initialize the swap file.  The necessary disk space is
1348*7917SReza.Sabdar@Sun.COM  * reserved by writing to the swap file for swapping the
1349*7917SReza.Sabdar@Sun.COM  * chunks in/out of the file.
1350*7917SReza.Sabdar@Sun.COM  */
1351*7917SReza.Sabdar@Sun.COM static int
1352*7917SReza.Sabdar@Sun.COM swfile_init(int fd, u_quad_t len, int set)
1353*7917SReza.Sabdar@Sun.COM {
1354*7917SReza.Sabdar@Sun.COM 	u_quad_t i, n;
1355*7917SReza.Sabdar@Sun.COM 	uint_t cl, ml;
1356*7917SReza.Sabdar@Sun.COM 	uint_t buf[BMAP_CHUNK_WORDS];
1357*7917SReza.Sabdar@Sun.COM 
1358*7917SReza.Sabdar@Sun.COM 	(void) memset(buf, set ? 0xff : 0x00, BMAP_CHUNK_BYTES);
1359*7917SReza.Sabdar@Sun.COM 	n = len / BMAP_CHUNK_BITS;
1360*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < n; i++)
1361*7917SReza.Sabdar@Sun.COM 		if (write(fd, buf, BMAP_CHUNK_BYTES) != BMAP_CHUNK_BYTES)
1362*7917SReza.Sabdar@Sun.COM 			return (-1);
1363*7917SReza.Sabdar@Sun.COM 
1364*7917SReza.Sabdar@Sun.COM 	cl = (uint_t)(len % BMAP_CHUNK_BITS);
1365*7917SReza.Sabdar@Sun.COM 	ml = MEM_LEN(cl);
1366*7917SReza.Sabdar@Sun.COM 	if (write(fd, buf, ml) != ml)
1367*7917SReza.Sabdar@Sun.COM 		return (-1);
1368*7917SReza.Sabdar@Sun.COM 
1369*7917SReza.Sabdar@Sun.COM 	return (swfile_trunc(fd));
1370*7917SReza.Sabdar@Sun.COM }
1371*7917SReza.Sabdar@Sun.COM 
1372*7917SReza.Sabdar@Sun.COM 
1373*7917SReza.Sabdar@Sun.COM /*
1374*7917SReza.Sabdar@Sun.COM  * dbm_alloc
1375*7917SReza.Sabdar@Sun.COM  *
1376*7917SReza.Sabdar@Sun.COM  * Allocate a bit map and return a handle to it.
1377*7917SReza.Sabdar@Sun.COM  *
1378*7917SReza.Sabdar@Sun.COM  * The swap file is created if it does not exist.
1379*7917SReza.Sabdar@Sun.COM  * The file is truncated if it exists and is larger
1380*7917SReza.Sabdar@Sun.COM  * than needed amount.
1381*7917SReza.Sabdar@Sun.COM  *
1382*7917SReza.Sabdar@Sun.COM  * The hash table and LRU list are empty at this point.
1383*7917SReza.Sabdar@Sun.COM  * They are allocated and/or loaded on-demand.
1384*7917SReza.Sabdar@Sun.COM  */
1385*7917SReza.Sabdar@Sun.COM int
1386*7917SReza.Sabdar@Sun.COM dbm_alloc(char *fname, u_quad_t len, int set)
1387*7917SReza.Sabdar@Sun.COM {
1388*7917SReza.Sabdar@Sun.COM 	int fd;
1389*7917SReza.Sabdar@Sun.COM 	int bmd;
1390*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1391*7917SReza.Sabdar@Sun.COM 
1392*7917SReza.Sabdar@Sun.COM 	if (!fname || !*fname || !len)
1393*7917SReza.Sabdar@Sun.COM 		return (-1);
1394*7917SReza.Sabdar@Sun.COM 
1395*7917SReza.Sabdar@Sun.COM 	/*
1396*7917SReza.Sabdar@Sun.COM 	 * When allocating bitmap, make sure there is enough
1397*7917SReza.Sabdar@Sun.COM 	 * disk space by allocating needed disk space, for
1398*7917SReza.Sabdar@Sun.COM 	 * writing back the dirty chunks when swaping them out.
1399*7917SReza.Sabdar@Sun.COM 	 */
1400*7917SReza.Sabdar@Sun.COM 	bmd = dbmd_alloc();
1401*7917SReza.Sabdar@Sun.COM 	if (bmd < 0)
1402*7917SReza.Sabdar@Sun.COM 		return (bmd);
1403*7917SReza.Sabdar@Sun.COM 
1404*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1405*7917SReza.Sabdar@Sun.COM 	if ((fd = open(fname, O_RDWR|O_CREAT, 0600)) < 0)
1406*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1407*7917SReza.Sabdar@Sun.COM 	else if (swfile_init(fd, len, set) < 0) {
1408*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1409*7917SReza.Sabdar@Sun.COM 		(void) close(fd);
1410*7917SReza.Sabdar@Sun.COM 		(void) unlink(fname);
1411*7917SReza.Sabdar@Sun.COM 		dbmd_free(bmd);
1412*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1413*7917SReza.Sabdar@Sun.COM 	} else if (!(bmp->bm_fname = strdup(fname))) {
1414*7917SReza.Sabdar@Sun.COM 		(void) close(fd);
1415*7917SReza.Sabdar@Sun.COM 		(void) unlink(fname);
1416*7917SReza.Sabdar@Sun.COM 		dbmd_free(bmd);
1417*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1418*7917SReza.Sabdar@Sun.COM 	} else {
1419*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_alloc_cnt++;
1420*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_alloc_size += len;
1421*7917SReza.Sabdar@Sun.COM 
1422*7917SReza.Sabdar@Sun.COM 		bmp->bm_fd = fd;
1423*7917SReza.Sabdar@Sun.COM 		if (set)
1424*7917SReza.Sabdar@Sun.COM 			BMAP_SET_FLAGS(bmp, BMAP_BINIT_ONES);
1425*7917SReza.Sabdar@Sun.COM 		else
1426*7917SReza.Sabdar@Sun.COM 			BMAP_UNSET_FLAGS(bmp, BMAP_BINIT_ONES);
1427*7917SReza.Sabdar@Sun.COM 		bmp->bm_len = len;
1428*7917SReza.Sabdar@Sun.COM 		bmp->bm_ccur = 0;
1429*7917SReza.Sabdar@Sun.COM 		bmp->bm_cmax = BMAP_CHUNK_MAX;
1430*7917SReza.Sabdar@Sun.COM 		/* LINTED: E_CONSTANT_CONDITION */
1431*7917SReza.Sabdar@Sun.COM 		TAILQ_INIT(&bmp->bm_lru);
1432*7917SReza.Sabdar@Sun.COM 		hash_init((bmap_list_t *)bmp->bm_hash);
1433*7917SReza.Sabdar@Sun.COM 	}
1434*7917SReza.Sabdar@Sun.COM 
1435*7917SReza.Sabdar@Sun.COM 	return (bmd);
1436*7917SReza.Sabdar@Sun.COM }
1437*7917SReza.Sabdar@Sun.COM 
1438*7917SReza.Sabdar@Sun.COM 
1439*7917SReza.Sabdar@Sun.COM /*
1440*7917SReza.Sabdar@Sun.COM  * dbm_free
1441*7917SReza.Sabdar@Sun.COM  *
1442*7917SReza.Sabdar@Sun.COM  * Free memory allocated for the bitmap and remove its swap file.
1443*7917SReza.Sabdar@Sun.COM  */
1444*7917SReza.Sabdar@Sun.COM int
1445*7917SReza.Sabdar@Sun.COM dbm_free(int bmd)
1446*7917SReza.Sabdar@Sun.COM {
1447*7917SReza.Sabdar@Sun.COM 	int rv;
1448*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1449*7917SReza.Sabdar@Sun.COM 
1450*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1451*7917SReza.Sabdar@Sun.COM 	if (bmp && BMAP_IS_INUSE(bmp)) {
1452*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_free_cnt++;
1453*7917SReza.Sabdar@Sun.COM 
1454*7917SReza.Sabdar@Sun.COM 		dbm_chunks_free(bmp);
1455*7917SReza.Sabdar@Sun.COM 		(void) close(bmp->bm_fd);
1456*7917SReza.Sabdar@Sun.COM 		(void) unlink(bmp->bm_fname);
1457*7917SReza.Sabdar@Sun.COM 		free(bmp->bm_fname);
1458*7917SReza.Sabdar@Sun.COM 		dbmd_free(bmd);
1459*7917SReza.Sabdar@Sun.COM 		rv = 0;
1460*7917SReza.Sabdar@Sun.COM 	} else
1461*7917SReza.Sabdar@Sun.COM 		rv = -1;
1462*7917SReza.Sabdar@Sun.COM 
1463*7917SReza.Sabdar@Sun.COM 	return (rv);
1464*7917SReza.Sabdar@Sun.COM }
1465*7917SReza.Sabdar@Sun.COM 
1466*7917SReza.Sabdar@Sun.COM 
1467*7917SReza.Sabdar@Sun.COM /*
1468*7917SReza.Sabdar@Sun.COM  * dbm_getlen
1469*7917SReza.Sabdar@Sun.COM  *
1470*7917SReza.Sabdar@Sun.COM  * Return length of the bitmap.
1471*7917SReza.Sabdar@Sun.COM  */
1472*7917SReza.Sabdar@Sun.COM u_quad_t
1473*7917SReza.Sabdar@Sun.COM dbm_getlen(int bmd)
1474*7917SReza.Sabdar@Sun.COM {
1475*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1476*7917SReza.Sabdar@Sun.COM 
1477*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1478*7917SReza.Sabdar@Sun.COM 	return (dbmp_getlen(bmp));
1479*7917SReza.Sabdar@Sun.COM }
1480*7917SReza.Sabdar@Sun.COM 
1481*7917SReza.Sabdar@Sun.COM 
1482*7917SReza.Sabdar@Sun.COM /*
1483*7917SReza.Sabdar@Sun.COM  * dbm_set
1484*7917SReza.Sabdar@Sun.COM  *
1485*7917SReza.Sabdar@Sun.COM  * Set a range of bits.
1486*7917SReza.Sabdar@Sun.COM  */
1487*7917SReza.Sabdar@Sun.COM int
1488*7917SReza.Sabdar@Sun.COM dbm_set(int bmd, u_quad_t start, u_quad_t len, uint_t val)
1489*7917SReza.Sabdar@Sun.COM {
1490*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1491*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1492*7917SReza.Sabdar@Sun.COM 
1493*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1494*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1495*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = &val;
1496*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1497*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1498*7917SReza.Sabdar@Sun.COM 
1499*7917SReza.Sabdar@Sun.COM 	return (dbm_setiov(bmd, &io));
1500*7917SReza.Sabdar@Sun.COM }
1501*7917SReza.Sabdar@Sun.COM 
1502*7917SReza.Sabdar@Sun.COM 
1503*7917SReza.Sabdar@Sun.COM /*
1504*7917SReza.Sabdar@Sun.COM  * dbm_getiov
1505*7917SReza.Sabdar@Sun.COM  *
1506*7917SReza.Sabdar@Sun.COM  * Get bits specified by the array of vectors.
1507*7917SReza.Sabdar@Sun.COM  */
1508*7917SReza.Sabdar@Sun.COM int
1509*7917SReza.Sabdar@Sun.COM dbm_getiov(int bmd, bm_io_t *iop)
1510*7917SReza.Sabdar@Sun.COM {
1511*7917SReza.Sabdar@Sun.COM 	int i;
1512*7917SReza.Sabdar@Sun.COM 	int rv;
1513*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
1514*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1515*7917SReza.Sabdar@Sun.COM 
1516*7917SReza.Sabdar@Sun.COM 	if (!iop)
1517*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1518*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2dbmp(bmd)))
1519*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1520*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
1521*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1522*7917SReza.Sabdar@Sun.COM 	else {
1523*7917SReza.Sabdar@Sun.COM 		rv = 0;
1524*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
1525*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++) {
1526*7917SReza.Sabdar@Sun.COM 			if (!vp)
1527*7917SReza.Sabdar@Sun.COM 				return (-EINVAL);
1528*7917SReza.Sabdar@Sun.COM 			rv |= dbmp_getval(bmp, vp);
1529*7917SReza.Sabdar@Sun.COM 		}
1530*7917SReza.Sabdar@Sun.COM 	}
1531*7917SReza.Sabdar@Sun.COM 
1532*7917SReza.Sabdar@Sun.COM 	return (rv);
1533*7917SReza.Sabdar@Sun.COM }
1534*7917SReza.Sabdar@Sun.COM 
1535*7917SReza.Sabdar@Sun.COM 
1536*7917SReza.Sabdar@Sun.COM /*
1537*7917SReza.Sabdar@Sun.COM  * dbm_setiov
1538*7917SReza.Sabdar@Sun.COM  *
1539*7917SReza.Sabdar@Sun.COM  * Set bits specified by the array of vectors.
1540*7917SReza.Sabdar@Sun.COM  */
1541*7917SReza.Sabdar@Sun.COM int
1542*7917SReza.Sabdar@Sun.COM dbm_setiov(int bmd, bm_io_t *iop)
1543*7917SReza.Sabdar@Sun.COM {
1544*7917SReza.Sabdar@Sun.COM 	int i;
1545*7917SReza.Sabdar@Sun.COM 	int rv;
1546*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
1547*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1548*7917SReza.Sabdar@Sun.COM 
1549*7917SReza.Sabdar@Sun.COM 	if (!iop)
1550*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1551*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2dbmp(bmd)))
1552*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1553*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
1554*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1555*7917SReza.Sabdar@Sun.COM 	else if (!iop->bmio_iov)
1556*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1557*7917SReza.Sabdar@Sun.COM 	else {
1558*7917SReza.Sabdar@Sun.COM 		rv = 0;
1559*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
1560*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++)
1561*7917SReza.Sabdar@Sun.COM 			rv |= dbmp_setval(bmp, vp);
1562*7917SReza.Sabdar@Sun.COM 	}
1563*7917SReza.Sabdar@Sun.COM 
1564*7917SReza.Sabdar@Sun.COM 	return (rv);
1565*7917SReza.Sabdar@Sun.COM }
1566*7917SReza.Sabdar@Sun.COM 
1567*7917SReza.Sabdar@Sun.COM 
1568*7917SReza.Sabdar@Sun.COM /*
1569*7917SReza.Sabdar@Sun.COM  * dbm_apply_ifset
1570*7917SReza.Sabdar@Sun.COM  *
1571*7917SReza.Sabdar@Sun.COM  * Call the callback function for each set bit in the bitmap and
1572*7917SReza.Sabdar@Sun.COM  * pass the 'arg' and bit number as its argument.
1573*7917SReza.Sabdar@Sun.COM  */
1574*7917SReza.Sabdar@Sun.COM int
1575*7917SReza.Sabdar@Sun.COM dbm_apply_ifset(int bmd, int(*fp)(), void *arg)
1576*7917SReza.Sabdar@Sun.COM {
1577*7917SReza.Sabdar@Sun.COM 	int rv;
1578*7917SReza.Sabdar@Sun.COM 	u_quad_t q;
1579*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1580*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1581*7917SReza.Sabdar@Sun.COM 
1582*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1583*7917SReza.Sabdar@Sun.COM 	if (!bmp || !fp)
1584*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
1585*7917SReza.Sabdar@Sun.COM 
1586*7917SReza.Sabdar@Sun.COM 	rv = 0;
1587*7917SReza.Sabdar@Sun.COM 	for (q = 0; q < bmp->bm_len; q += BMAP_CHUNK_BITS) {
1588*7917SReza.Sabdar@Sun.COM 		cp = dbm_chunk_find(bmp, q);
1589*7917SReza.Sabdar@Sun.COM 		if (!cp) {
1590*7917SReza.Sabdar@Sun.COM 			rv = -ERANGE;
1591*7917SReza.Sabdar@Sun.COM 			break;
1592*7917SReza.Sabdar@Sun.COM 		}
1593*7917SReza.Sabdar@Sun.COM 
1594*7917SReza.Sabdar@Sun.COM 		rv = dbm_chunk_apply_ifset(bmp, cp, fp, arg);
1595*7917SReza.Sabdar@Sun.COM 		if (rv != 0)
1596*7917SReza.Sabdar@Sun.COM 			break;
1597*7917SReza.Sabdar@Sun.COM 	}
1598*7917SReza.Sabdar@Sun.COM 
1599*7917SReza.Sabdar@Sun.COM 	return (rv);
1600*7917SReza.Sabdar@Sun.COM }
1601*7917SReza.Sabdar@Sun.COM 
1602*7917SReza.Sabdar@Sun.COM 
1603*7917SReza.Sabdar@Sun.COM /*
1604*7917SReza.Sabdar@Sun.COM  * bm_set
1605*7917SReza.Sabdar@Sun.COM  *
1606*7917SReza.Sabdar@Sun.COM  * Set a range of bits.
1607*7917SReza.Sabdar@Sun.COM  */
1608*7917SReza.Sabdar@Sun.COM int
1609*7917SReza.Sabdar@Sun.COM bm_set(int bmd, u_quad_t start, u_quad_t len, uint_t val)
1610*7917SReza.Sabdar@Sun.COM {
1611*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1612*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1613*7917SReza.Sabdar@Sun.COM 
1614*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1615*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1616*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = &val;
1617*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1618*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1619*7917SReza.Sabdar@Sun.COM 
1620*7917SReza.Sabdar@Sun.COM 	return (bm_setiov(bmd, &io));
1621*7917SReza.Sabdar@Sun.COM }
1622*7917SReza.Sabdar@Sun.COM 
1623*7917SReza.Sabdar@Sun.COM 
1624*7917SReza.Sabdar@Sun.COM /*
1625*7917SReza.Sabdar@Sun.COM  * bm_get
1626*7917SReza.Sabdar@Sun.COM  *
1627*7917SReza.Sabdar@Sun.COM  * Get a range of bits.
1628*7917SReza.Sabdar@Sun.COM  */
1629*7917SReza.Sabdar@Sun.COM int
1630*7917SReza.Sabdar@Sun.COM bm_get(int bmd, u_quad_t start, u_quad_t len, uint_t *buf)
1631*7917SReza.Sabdar@Sun.COM {
1632*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1633*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1634*7917SReza.Sabdar@Sun.COM 
1635*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1636*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1637*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = buf;
1638*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1639*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1640*7917SReza.Sabdar@Sun.COM 
1641*7917SReza.Sabdar@Sun.COM 	return (bm_getiov(bmd, &io));
1642*7917SReza.Sabdar@Sun.COM }
1643*7917SReza.Sabdar@Sun.COM 
1644*7917SReza.Sabdar@Sun.COM 
1645*7917SReza.Sabdar@Sun.COM /*
1646*7917SReza.Sabdar@Sun.COM  * bm_getone
1647*7917SReza.Sabdar@Sun.COM  *
1648*7917SReza.Sabdar@Sun.COM  * Get only one bit.
1649*7917SReza.Sabdar@Sun.COM  */
1650*7917SReza.Sabdar@Sun.COM int
1651*7917SReza.Sabdar@Sun.COM bm_getone(int bmd, u_quad_t bitnum)
1652*7917SReza.Sabdar@Sun.COM {
1653*7917SReza.Sabdar@Sun.COM 	uint_t i;
1654*7917SReza.Sabdar@Sun.COM 
1655*7917SReza.Sabdar@Sun.COM 	if (bm_get(bmd, bitnum, 1, &i) == 0)
1656*7917SReza.Sabdar@Sun.COM 		return (i ? 1 : 0);
1657*7917SReza.Sabdar@Sun.COM 
1658*7917SReza.Sabdar@Sun.COM 	return (0);
1659*7917SReza.Sabdar@Sun.COM }
1660*7917SReza.Sabdar@Sun.COM 
1661*7917SReza.Sabdar@Sun.COM 
1662*7917SReza.Sabdar@Sun.COM /*
1663*7917SReza.Sabdar@Sun.COM  * dbm_get
1664*7917SReza.Sabdar@Sun.COM  *
1665*7917SReza.Sabdar@Sun.COM  * Get a range of bits.
1666*7917SReza.Sabdar@Sun.COM  */
1667*7917SReza.Sabdar@Sun.COM int
1668*7917SReza.Sabdar@Sun.COM dbm_get(int bmd, u_quad_t start, u_quad_t len, uint_t *buf)
1669*7917SReza.Sabdar@Sun.COM {
1670*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1671*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1672*7917SReza.Sabdar@Sun.COM 
1673*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1674*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1675*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = buf;
1676*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1677*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1678*7917SReza.Sabdar@Sun.COM 
1679*7917SReza.Sabdar@Sun.COM 	return (dbm_getiov(bmd, &io));
1680*7917SReza.Sabdar@Sun.COM }
1681*7917SReza.Sabdar@Sun.COM 
1682*7917SReza.Sabdar@Sun.COM 
1683*7917SReza.Sabdar@Sun.COM /*
1684*7917SReza.Sabdar@Sun.COM  * dbm_getone
1685*7917SReza.Sabdar@Sun.COM  *
1686*7917SReza.Sabdar@Sun.COM  * Get only one bit.
1687*7917SReza.Sabdar@Sun.COM  */
1688*7917SReza.Sabdar@Sun.COM int
1689*7917SReza.Sabdar@Sun.COM dbm_getone(int bmd, u_quad_t bitnum)
1690*7917SReza.Sabdar@Sun.COM {
1691*7917SReza.Sabdar@Sun.COM 	uint_t i;
1692*7917SReza.Sabdar@Sun.COM 
1693*7917SReza.Sabdar@Sun.COM 	if (dbm_get(bmd, bitnum, 1, &i) == 0)
1694*7917SReza.Sabdar@Sun.COM 		return (i ? 1 : 0);
1695*7917SReza.Sabdar@Sun.COM 
1696*7917SReza.Sabdar@Sun.COM 	return (0);
1697*7917SReza.Sabdar@Sun.COM }
1698