xref: /onnv-gate/usr/src/cmd/ndmpd/tlm/tlm_bitmap.c (revision 8731:accad831e993)
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 *
bmd2bmp(int bmd)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
bmd_alloc(void)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
bmd_free(int bmd)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
bmp_set(bmap_chunk_t * cp,u_quad_t bn,uint_t * vp)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
bmp_get(bmap_chunk_t * cp,u_quad_t bn)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 *
bm_chunk_setup(bitmap_t * bmp,bmap_chunk_t * cp,u_quad_t bn)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 	TAILQ_INSERT_HEAD(hp, cp, c_hash);
394*7917SReza.Sabdar@Sun.COM 	cp->c_off = off;
395*7917SReza.Sabdar@Sun.COM 	cp->c_clen = cl;
396*7917SReza.Sabdar@Sun.COM 	cp->c_mlen = ml;
397*7917SReza.Sabdar@Sun.COM 	return (cp);
398*7917SReza.Sabdar@Sun.COM }
399*7917SReza.Sabdar@Sun.COM 
400*7917SReza.Sabdar@Sun.COM 
401*7917SReza.Sabdar@Sun.COM /*
402*7917SReza.Sabdar@Sun.COM  * bm_chunk_new
403*7917SReza.Sabdar@Sun.COM  *
404*7917SReza.Sabdar@Sun.COM  * Create a new chunk and keep track of memory used.
405*7917SReza.Sabdar@Sun.COM  */
406*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
bm_chunk_new(bitmap_t * bmp,u_quad_t bn)407*7917SReza.Sabdar@Sun.COM bm_chunk_new(bitmap_t *bmp, u_quad_t bn)
408*7917SReza.Sabdar@Sun.COM {
409*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
410*7917SReza.Sabdar@Sun.COM 
411*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_new++;
412*7917SReza.Sabdar@Sun.COM 
413*7917SReza.Sabdar@Sun.COM 	cp = ndmp_malloc(sizeof (bmap_chunk_t));
414*7917SReza.Sabdar@Sun.COM 	if (cp) {
415*7917SReza.Sabdar@Sun.COM 		cp->c_bmp = ndmp_malloc(sizeof (uint_t) * BMAP_CHUNK_WORDS);
416*7917SReza.Sabdar@Sun.COM 		if (!cp->c_bmp) {
417*7917SReza.Sabdar@Sun.COM 			free(cp);
418*7917SReza.Sabdar@Sun.COM 			cp = NULL;
419*7917SReza.Sabdar@Sun.COM 		} else {
420*7917SReza.Sabdar@Sun.COM 			(void) bm_chunk_setup(bmp, cp, bn);
421*7917SReza.Sabdar@Sun.COM 			bmp->bm_ccur++;
422*7917SReza.Sabdar@Sun.COM 		}
423*7917SReza.Sabdar@Sun.COM 	}
424*7917SReza.Sabdar@Sun.COM 
425*7917SReza.Sabdar@Sun.COM 	return (cp);
426*7917SReza.Sabdar@Sun.COM }
427*7917SReza.Sabdar@Sun.COM 
428*7917SReza.Sabdar@Sun.COM 
429*7917SReza.Sabdar@Sun.COM /*
430*7917SReza.Sabdar@Sun.COM  * bm_chunk_alloc
431*7917SReza.Sabdar@Sun.COM  *
432*7917SReza.Sabdar@Sun.COM  * Allocate a chunk and return it.  If the cache for the chunks is not
433*7917SReza.Sabdar@Sun.COM  * fully used, a new chunk is created.
434*7917SReza.Sabdar@Sun.COM  */
435*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
bm_chunk_alloc(bitmap_t * bmp,u_quad_t bn)436*7917SReza.Sabdar@Sun.COM bm_chunk_alloc(bitmap_t *bmp, u_quad_t bn)
437*7917SReza.Sabdar@Sun.COM {
438*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
439*7917SReza.Sabdar@Sun.COM 
440*7917SReza.Sabdar@Sun.COM 	if (bmp->bm_ccur < bmp->bm_cmax)
441*7917SReza.Sabdar@Sun.COM 		cp = bm_chunk_new(bmp, bn);
442*7917SReza.Sabdar@Sun.COM 	else
443*7917SReza.Sabdar@Sun.COM 		cp = NULL;
444*7917SReza.Sabdar@Sun.COM 
445*7917SReza.Sabdar@Sun.COM 	return (cp);
446*7917SReza.Sabdar@Sun.COM }
447*7917SReza.Sabdar@Sun.COM 
448*7917SReza.Sabdar@Sun.COM 
449*7917SReza.Sabdar@Sun.COM /*
450*7917SReza.Sabdar@Sun.COM  * hash_free
451*7917SReza.Sabdar@Sun.COM  *
452*7917SReza.Sabdar@Sun.COM  * Free all chunks on the hash list.
453*7917SReza.Sabdar@Sun.COM  */
454*7917SReza.Sabdar@Sun.COM void
hash_free(bmap_list_t * hp)455*7917SReza.Sabdar@Sun.COM hash_free(bmap_list_t *hp)
456*7917SReza.Sabdar@Sun.COM {
457*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
458*7917SReza.Sabdar@Sun.COM 
459*7917SReza.Sabdar@Sun.COM 	if (!hp)
460*7917SReza.Sabdar@Sun.COM 		return;
461*7917SReza.Sabdar@Sun.COM 
462*7917SReza.Sabdar@Sun.COM 	while (!TAILQ_EMPTY(hp)) {
463*7917SReza.Sabdar@Sun.COM 		cp = TAILQ_FIRST(hp);
464*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(hp, cp, c_hash);
465*7917SReza.Sabdar@Sun.COM 		free(cp->c_bmp);
466*7917SReza.Sabdar@Sun.COM 		free(cp);
467*7917SReza.Sabdar@Sun.COM 	}
468*7917SReza.Sabdar@Sun.COM }
469*7917SReza.Sabdar@Sun.COM 
470*7917SReza.Sabdar@Sun.COM 
471*7917SReza.Sabdar@Sun.COM /*
472*7917SReza.Sabdar@Sun.COM  * bm_chunks_free
473*7917SReza.Sabdar@Sun.COM  *
474*7917SReza.Sabdar@Sun.COM  * Release the memory allocated for the chunks.
475*7917SReza.Sabdar@Sun.COM  */
476*7917SReza.Sabdar@Sun.COM static void
bm_chunks_free(bmap_list_t * hp)477*7917SReza.Sabdar@Sun.COM bm_chunks_free(bmap_list_t *hp)
478*7917SReza.Sabdar@Sun.COM {
479*7917SReza.Sabdar@Sun.COM 	int i;
480*7917SReza.Sabdar@Sun.COM 
481*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_HASH_SIZE; hp++, i++)
482*7917SReza.Sabdar@Sun.COM 		hash_free(hp);
483*7917SReza.Sabdar@Sun.COM }
484*7917SReza.Sabdar@Sun.COM 
485*7917SReza.Sabdar@Sun.COM 
486*7917SReza.Sabdar@Sun.COM /*
487*7917SReza.Sabdar@Sun.COM  * bm_chunk_repositions
488*7917SReza.Sabdar@Sun.COM  *
489*7917SReza.Sabdar@Sun.COM  * Re-position the chunk in the MRU hash table.
490*7917SReza.Sabdar@Sun.COM  */
491*7917SReza.Sabdar@Sun.COM static void
bm_chunk_reposition(bitmap_t * bmp,bmap_list_t * hp,bmap_chunk_t * cp)492*7917SReza.Sabdar@Sun.COM bm_chunk_reposition(bitmap_t *bmp, bmap_list_t *hp, bmap_chunk_t *cp)
493*7917SReza.Sabdar@Sun.COM {
494*7917SReza.Sabdar@Sun.COM 	if (!bmp || !hp || !cp)
495*7917SReza.Sabdar@Sun.COM 		return;
496*7917SReza.Sabdar@Sun.COM 
497*7917SReza.Sabdar@Sun.COM 	if (TAILQ_FIRST(hp) != cp) {
498*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(hp, cp, c_hash);
499*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_HEAD(hp, cp, c_hash);
500*7917SReza.Sabdar@Sun.COM 	}
501*7917SReza.Sabdar@Sun.COM }
502*7917SReza.Sabdar@Sun.COM 
503*7917SReza.Sabdar@Sun.COM 
504*7917SReza.Sabdar@Sun.COM /*
505*7917SReza.Sabdar@Sun.COM  * bm_chunk_find
506*7917SReza.Sabdar@Sun.COM  *
507*7917SReza.Sabdar@Sun.COM  * Find and return the chunks which holds the specified bit. Allocate
508*7917SReza.Sabdar@Sun.COM  * the chunk if necessary and re-position it in the hash table lists.
509*7917SReza.Sabdar@Sun.COM  */
510*7917SReza.Sabdar@Sun.COM static bmap_chunk_t *
bm_chunk_find(bitmap_t * bmp,u_quad_t bn)511*7917SReza.Sabdar@Sun.COM bm_chunk_find(bitmap_t *bmp, u_quad_t bn)
512*7917SReza.Sabdar@Sun.COM {
513*7917SReza.Sabdar@Sun.COM 	int h;
514*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
515*7917SReza.Sabdar@Sun.COM 	bmap_list_t *hp;
516*7917SReza.Sabdar@Sun.COM 
517*7917SReza.Sabdar@Sun.COM 	if (!bmp)
518*7917SReza.Sabdar@Sun.COM 		return (NULL);
519*7917SReza.Sabdar@Sun.COM 
520*7917SReza.Sabdar@Sun.COM 	h = HASH(bn);
521*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
522*7917SReza.Sabdar@Sun.COM 	TAILQ_FOREACH(cp, hp, c_hash) {
523*7917SReza.Sabdar@Sun.COM 		if (bn >= cp->c_off && bn < (cp->c_off + cp->c_clen)) {
524*7917SReza.Sabdar@Sun.COM 			bitmap_stats.bs_cache_hit++;
525*7917SReza.Sabdar@Sun.COM 
526*7917SReza.Sabdar@Sun.COM 			bm_chunk_reposition(bmp, hp, cp);
527*7917SReza.Sabdar@Sun.COM 			return (cp);
528*7917SReza.Sabdar@Sun.COM 		}
529*7917SReza.Sabdar@Sun.COM 	}
530*7917SReza.Sabdar@Sun.COM 
531*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_cache_miss++;
532*7917SReza.Sabdar@Sun.COM 
533*7917SReza.Sabdar@Sun.COM 	return (bm_chunk_alloc(bmp, bn));
534*7917SReza.Sabdar@Sun.COM }
535*7917SReza.Sabdar@Sun.COM 
536*7917SReza.Sabdar@Sun.COM 
537*7917SReza.Sabdar@Sun.COM /*
538*7917SReza.Sabdar@Sun.COM  * bmp_setval
539*7917SReza.Sabdar@Sun.COM  *
540*7917SReza.Sabdar@Sun.COM  * Set a range of bits in the bitmap specified by the vector.
541*7917SReza.Sabdar@Sun.COM  */
542*7917SReza.Sabdar@Sun.COM static int
bmp_setval(bitmap_t * bmp,bm_iovec_t * vp)543*7917SReza.Sabdar@Sun.COM bmp_setval(bitmap_t *bmp, bm_iovec_t *vp)
544*7917SReza.Sabdar@Sun.COM {
545*7917SReza.Sabdar@Sun.COM 	int rv;
546*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
547*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
548*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
549*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
550*7917SReza.Sabdar@Sun.COM 
551*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
552*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
553*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
554*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
555*7917SReza.Sabdar@Sun.COM 
556*7917SReza.Sabdar@Sun.COM 	if (*vp->bmv_val) {
557*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set++;
558*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set_bits += vp->bmv_len;
559*7917SReza.Sabdar@Sun.COM 	} else {
560*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset++;
561*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset_bits += vp->bmv_len;
562*7917SReza.Sabdar@Sun.COM 	}
563*7917SReza.Sabdar@Sun.COM 
564*7917SReza.Sabdar@Sun.COM 	do {
565*7917SReza.Sabdar@Sun.COM 		cp = bm_chunk_find(bmp, bn);
566*7917SReza.Sabdar@Sun.COM 		if (!cp)
567*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
568*7917SReza.Sabdar@Sun.COM 
569*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
570*7917SReza.Sabdar@Sun.COM 			rv = bmp_set(cp, bn, vp->bmv_val);
571*7917SReza.Sabdar@Sun.COM 			if (rv != 0)
572*7917SReza.Sabdar@Sun.COM 				return (rv);
573*7917SReza.Sabdar@Sun.COM 		}
574*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
575*7917SReza.Sabdar@Sun.COM 
576*7917SReza.Sabdar@Sun.COM 	return (0);
577*7917SReza.Sabdar@Sun.COM }
578*7917SReza.Sabdar@Sun.COM 
579*7917SReza.Sabdar@Sun.COM 
580*7917SReza.Sabdar@Sun.COM /*
581*7917SReza.Sabdar@Sun.COM  * bmp_getval
582*7917SReza.Sabdar@Sun.COM  *
583*7917SReza.Sabdar@Sun.COM  * Get a range of bits in the bitmap specified by the vector.
584*7917SReza.Sabdar@Sun.COM  */
585*7917SReza.Sabdar@Sun.COM static int
bmp_getval(bitmap_t * bmp,bm_iovec_t * vp)586*7917SReza.Sabdar@Sun.COM bmp_getval(bitmap_t *bmp, bm_iovec_t *vp)
587*7917SReza.Sabdar@Sun.COM {
588*7917SReza.Sabdar@Sun.COM 	uint_t cnt;
589*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
590*7917SReza.Sabdar@Sun.COM 	int rv;
591*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
592*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
593*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
594*7917SReza.Sabdar@Sun.COM 	bmap_chunk_t *cp;
595*7917SReza.Sabdar@Sun.COM 
596*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
597*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
598*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
599*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
600*7917SReza.Sabdar@Sun.COM 
601*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get++;
602*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get_bits += 1;
603*7917SReza.Sabdar@Sun.COM 
604*7917SReza.Sabdar@Sun.COM 	cnt = 0;
605*7917SReza.Sabdar@Sun.COM 	ip = vp->bmv_val;
606*7917SReza.Sabdar@Sun.COM 	*ip = 0;
607*7917SReza.Sabdar@Sun.COM 	do {
608*7917SReza.Sabdar@Sun.COM 		cp = bm_chunk_find(bmp, bn);
609*7917SReza.Sabdar@Sun.COM 		if (!cp)
610*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
611*7917SReza.Sabdar@Sun.COM 
612*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
613*7917SReza.Sabdar@Sun.COM 			rv = bmp_get(cp, bn);
614*7917SReza.Sabdar@Sun.COM 			if (rv < 0)
615*7917SReza.Sabdar@Sun.COM 				return (rv);
616*7917SReza.Sabdar@Sun.COM 
617*7917SReza.Sabdar@Sun.COM 			*ip |= rv << cnt;
618*7917SReza.Sabdar@Sun.COM 			if (++cnt >= BMAP_BPW) {
619*7917SReza.Sabdar@Sun.COM 				*++ip = 0;
620*7917SReza.Sabdar@Sun.COM 				cnt = 0;
621*7917SReza.Sabdar@Sun.COM 			}
622*7917SReza.Sabdar@Sun.COM 		}
623*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
624*7917SReza.Sabdar@Sun.COM 
625*7917SReza.Sabdar@Sun.COM 	return (0);
626*7917SReza.Sabdar@Sun.COM }
627*7917SReza.Sabdar@Sun.COM 
628*7917SReza.Sabdar@Sun.COM 
629*7917SReza.Sabdar@Sun.COM /*
630*7917SReza.Sabdar@Sun.COM  * hash_init
631*7917SReza.Sabdar@Sun.COM  *
632*7917SReza.Sabdar@Sun.COM  * Initialize the hash table lists head.
633*7917SReza.Sabdar@Sun.COM  */
634*7917SReza.Sabdar@Sun.COM static void
hash_init(bmap_list_t * hp)635*7917SReza.Sabdar@Sun.COM hash_init(bmap_list_t *hp)
636*7917SReza.Sabdar@Sun.COM {
637*7917SReza.Sabdar@Sun.COM 	int i;
638*7917SReza.Sabdar@Sun.COM 
639*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_HASH_SIZE; hp++, i++) {
640*7917SReza.Sabdar@Sun.COM 		TAILQ_INIT(hp);
641*7917SReza.Sabdar@Sun.COM 	}
642*7917SReza.Sabdar@Sun.COM }
643*7917SReza.Sabdar@Sun.COM 
644*7917SReza.Sabdar@Sun.COM 
645*7917SReza.Sabdar@Sun.COM /*
646*7917SReza.Sabdar@Sun.COM  * bm_alloc
647*7917SReza.Sabdar@Sun.COM  *
648*7917SReza.Sabdar@Sun.COM  * Allocate a bit map and return a handle to it.
649*7917SReza.Sabdar@Sun.COM  *
650*7917SReza.Sabdar@Sun.COM  * The hash table list are empty at this point. They are allocated
651*7917SReza.Sabdar@Sun.COM  * on demand.
652*7917SReza.Sabdar@Sun.COM  */
653*7917SReza.Sabdar@Sun.COM int
bm_alloc(u_quad_t len,int set)654*7917SReza.Sabdar@Sun.COM bm_alloc(u_quad_t len, int set)
655*7917SReza.Sabdar@Sun.COM {
656*7917SReza.Sabdar@Sun.COM 	int bmd;
657*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
658*7917SReza.Sabdar@Sun.COM 
659*7917SReza.Sabdar@Sun.COM 	if (len == 0)
660*7917SReza.Sabdar@Sun.COM 		return (-1);
661*7917SReza.Sabdar@Sun.COM 
662*7917SReza.Sabdar@Sun.COM 	bmd = bmd_alloc();
663*7917SReza.Sabdar@Sun.COM 	if (bmd < 0)
664*7917SReza.Sabdar@Sun.COM 		return (bmd);
665*7917SReza.Sabdar@Sun.COM 
666*7917SReza.Sabdar@Sun.COM 	bmp = bmd2bmp(bmd);
667*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_alloc_cnt++;
668*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_alloc_size += len;
669*7917SReza.Sabdar@Sun.COM 
670*7917SReza.Sabdar@Sun.COM 	if (set)
671*7917SReza.Sabdar@Sun.COM 		BMAP_SET_FLAGS(bmp, BMAP_BINIT_ONES);
672*7917SReza.Sabdar@Sun.COM 	else
673*7917SReza.Sabdar@Sun.COM 		BMAP_UNSET_FLAGS(bmp, BMAP_BINIT_ONES);
674*7917SReza.Sabdar@Sun.COM 	bmp->bm_len = len;
675*7917SReza.Sabdar@Sun.COM 	bmp->bm_ccur = 0;
676*7917SReza.Sabdar@Sun.COM 	bmp->bm_cmax = BMAP_CHUNK_MAX;
677*7917SReza.Sabdar@Sun.COM 	hash_init(bmp->bm_hash);
678*7917SReza.Sabdar@Sun.COM 
679*7917SReza.Sabdar@Sun.COM 	return (bmd);
680*7917SReza.Sabdar@Sun.COM }
681*7917SReza.Sabdar@Sun.COM 
682*7917SReza.Sabdar@Sun.COM 
683*7917SReza.Sabdar@Sun.COM /*
684*7917SReza.Sabdar@Sun.COM  * bm_free
685*7917SReza.Sabdar@Sun.COM  *
686*7917SReza.Sabdar@Sun.COM  * Free memory allocated for the bitmap.
687*7917SReza.Sabdar@Sun.COM  */
688*7917SReza.Sabdar@Sun.COM int
bm_free(int bmd)689*7917SReza.Sabdar@Sun.COM bm_free(int bmd)
690*7917SReza.Sabdar@Sun.COM {
691*7917SReza.Sabdar@Sun.COM 	int rv;
692*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
693*7917SReza.Sabdar@Sun.COM 
694*7917SReza.Sabdar@Sun.COM 	bmp = bmd2bmp(bmd);
695*7917SReza.Sabdar@Sun.COM 	if (bmp && BMAP_IS_INUSE(bmp)) {
696*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_free_cnt++;
697*7917SReza.Sabdar@Sun.COM 
698*7917SReza.Sabdar@Sun.COM 		bm_chunks_free(bmp->bm_hash);
699*7917SReza.Sabdar@Sun.COM 		bmd_free(bmd);
700*7917SReza.Sabdar@Sun.COM 		rv = 0;
701*7917SReza.Sabdar@Sun.COM 	} else
702*7917SReza.Sabdar@Sun.COM 		rv = -1;
703*7917SReza.Sabdar@Sun.COM 
704*7917SReza.Sabdar@Sun.COM 	return (rv);
705*7917SReza.Sabdar@Sun.COM }
706*7917SReza.Sabdar@Sun.COM 
707*7917SReza.Sabdar@Sun.COM 
708*7917SReza.Sabdar@Sun.COM /*
709*7917SReza.Sabdar@Sun.COM  * bm_getiov
710*7917SReza.Sabdar@Sun.COM  *
711*7917SReza.Sabdar@Sun.COM  * Get bits specified by the array of vectors.
712*7917SReza.Sabdar@Sun.COM  */
713*7917SReza.Sabdar@Sun.COM int
bm_getiov(int bmd,bm_io_t * iop)714*7917SReza.Sabdar@Sun.COM bm_getiov(int bmd, bm_io_t *iop)
715*7917SReza.Sabdar@Sun.COM {
716*7917SReza.Sabdar@Sun.COM 	int i;
717*7917SReza.Sabdar@Sun.COM 	int rv;
718*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
719*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
720*7917SReza.Sabdar@Sun.COM 
721*7917SReza.Sabdar@Sun.COM 	if (!iop)
722*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
723*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2bmp(bmd)))
724*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
725*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
726*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
727*7917SReza.Sabdar@Sun.COM 	else {
728*7917SReza.Sabdar@Sun.COM 		rv = 0;
729*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
730*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++) {
731*7917SReza.Sabdar@Sun.COM 			if (!vp)
732*7917SReza.Sabdar@Sun.COM 				return (-EINVAL);
733*7917SReza.Sabdar@Sun.COM 			rv |= bmp_getval(bmp, vp);
734*7917SReza.Sabdar@Sun.COM 		}
735*7917SReza.Sabdar@Sun.COM 	}
736*7917SReza.Sabdar@Sun.COM 
737*7917SReza.Sabdar@Sun.COM 	return (rv);
738*7917SReza.Sabdar@Sun.COM }
739*7917SReza.Sabdar@Sun.COM 
740*7917SReza.Sabdar@Sun.COM 
741*7917SReza.Sabdar@Sun.COM /*
742*7917SReza.Sabdar@Sun.COM  * bm_setiov
743*7917SReza.Sabdar@Sun.COM  *
744*7917SReza.Sabdar@Sun.COM  * Set bits specified by the array of vectors.
745*7917SReza.Sabdar@Sun.COM  */
746*7917SReza.Sabdar@Sun.COM int
bm_setiov(int bmd,bm_io_t * iop)747*7917SReza.Sabdar@Sun.COM bm_setiov(int bmd, bm_io_t *iop)
748*7917SReza.Sabdar@Sun.COM {
749*7917SReza.Sabdar@Sun.COM 	int i;
750*7917SReza.Sabdar@Sun.COM 	int rv;
751*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
752*7917SReza.Sabdar@Sun.COM 	bitmap_t *bmp;
753*7917SReza.Sabdar@Sun.COM 
754*7917SReza.Sabdar@Sun.COM 	if (!iop)
755*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
756*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2bmp(bmd)))
757*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
758*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
759*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
760*7917SReza.Sabdar@Sun.COM 	else if (!iop->bmio_iov)
761*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
762*7917SReza.Sabdar@Sun.COM 	else {
763*7917SReza.Sabdar@Sun.COM 		rv = 0;
764*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
765*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++)
766*7917SReza.Sabdar@Sun.COM 			rv |= bmp_setval(bmp, vp);
767*7917SReza.Sabdar@Sun.COM 	}
768*7917SReza.Sabdar@Sun.COM 
769*7917SReza.Sabdar@Sun.COM 	return (rv);
770*7917SReza.Sabdar@Sun.COM }
771*7917SReza.Sabdar@Sun.COM 
772*7917SReza.Sabdar@Sun.COM 
773*7917SReza.Sabdar@Sun.COM /*
774*7917SReza.Sabdar@Sun.COM  * bmd2dbmp
775*7917SReza.Sabdar@Sun.COM  *
776*7917SReza.Sabdar@Sun.COM  * Convert bitmap descriptor to bitmap pointer.
777*7917SReza.Sabdar@Sun.COM  */
778*7917SReza.Sabdar@Sun.COM static dbitmap_t *
bmd2dbmp(int bmd)779*7917SReza.Sabdar@Sun.COM bmd2dbmp(int bmd)
780*7917SReza.Sabdar@Sun.COM {
781*7917SReza.Sabdar@Sun.COM 	if (bmd < 0 || bmd >= BMAP_MAX)
782*7917SReza.Sabdar@Sun.COM 		return (NULL);
783*7917SReza.Sabdar@Sun.COM 
784*7917SReza.Sabdar@Sun.COM 	return (&dbitmap[bmd]);
785*7917SReza.Sabdar@Sun.COM }
786*7917SReza.Sabdar@Sun.COM 
787*7917SReza.Sabdar@Sun.COM 
788*7917SReza.Sabdar@Sun.COM /*
789*7917SReza.Sabdar@Sun.COM  * dbmp2bmd
790*7917SReza.Sabdar@Sun.COM  *
791*7917SReza.Sabdar@Sun.COM  * Convert bitmap pointer to bitmap descriptor.
792*7917SReza.Sabdar@Sun.COM  */
793*7917SReza.Sabdar@Sun.COM static int
dbmp2bmd(dbitmap_t * bmp)794*7917SReza.Sabdar@Sun.COM dbmp2bmd(dbitmap_t *bmp)
795*7917SReza.Sabdar@Sun.COM {
796*7917SReza.Sabdar@Sun.COM 	int bmd;
797*7917SReza.Sabdar@Sun.COM 
798*7917SReza.Sabdar@Sun.COM 	bmd = bmp - dbitmap;
799*7917SReza.Sabdar@Sun.COM 	if (bmd < 0 || bmd >= BMAP_MAX)
800*7917SReza.Sabdar@Sun.COM 		bmd = -1;
801*7917SReza.Sabdar@Sun.COM 
802*7917SReza.Sabdar@Sun.COM 	return (bmd);
803*7917SReza.Sabdar@Sun.COM }
804*7917SReza.Sabdar@Sun.COM 
805*7917SReza.Sabdar@Sun.COM /*
806*7917SReza.Sabdar@Sun.COM  * dbmd_alloc
807*7917SReza.Sabdar@Sun.COM  *
808*7917SReza.Sabdar@Sun.COM  * Allocate a bitmap descriptor.
809*7917SReza.Sabdar@Sun.COM  * Sets the INUSE flag of the slot.
810*7917SReza.Sabdar@Sun.COM  */
811*7917SReza.Sabdar@Sun.COM static int
dbmd_alloc(void)812*7917SReza.Sabdar@Sun.COM dbmd_alloc(void)
813*7917SReza.Sabdar@Sun.COM {
814*7917SReza.Sabdar@Sun.COM 	int i;
815*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
816*7917SReza.Sabdar@Sun.COM 
817*7917SReza.Sabdar@Sun.COM 	bmp = dbitmap;
818*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < BMAP_MAX; bmp++, i++)
819*7917SReza.Sabdar@Sun.COM 		if (!BMAP_IS_INUSE(bmp)) {
820*7917SReza.Sabdar@Sun.COM 			BMAP_SET_FLAGS(bmp, BMAP_INUSE);
821*7917SReza.Sabdar@Sun.COM 			return (i);
822*7917SReza.Sabdar@Sun.COM 		}
823*7917SReza.Sabdar@Sun.COM 
824*7917SReza.Sabdar@Sun.COM 	return (-1);
825*7917SReza.Sabdar@Sun.COM }
826*7917SReza.Sabdar@Sun.COM 
827*7917SReza.Sabdar@Sun.COM 
828*7917SReza.Sabdar@Sun.COM /*
829*7917SReza.Sabdar@Sun.COM  * dbmd_free
830*7917SReza.Sabdar@Sun.COM  *
831*7917SReza.Sabdar@Sun.COM  * Free a bitmap descriptor.
832*7917SReza.Sabdar@Sun.COM  * Clears the INUSE flag of the slot.
833*7917SReza.Sabdar@Sun.COM  */
834*7917SReza.Sabdar@Sun.COM static void
dbmd_free(int bmd)835*7917SReza.Sabdar@Sun.COM dbmd_free(int bmd)
836*7917SReza.Sabdar@Sun.COM {
837*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
838*7917SReza.Sabdar@Sun.COM 
839*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
840*7917SReza.Sabdar@Sun.COM 	if (bmp)
841*7917SReza.Sabdar@Sun.COM 		BMAP_UNSET_FLAGS(bmp, BMAP_INUSE);
842*7917SReza.Sabdar@Sun.COM }
843*7917SReza.Sabdar@Sun.COM 
844*7917SReza.Sabdar@Sun.COM 
845*7917SReza.Sabdar@Sun.COM /*
846*7917SReza.Sabdar@Sun.COM  * dbmp_set
847*7917SReza.Sabdar@Sun.COM  *
848*7917SReza.Sabdar@Sun.COM  * Generic function to set bit in a chunk.  This can
849*7917SReza.Sabdar@Sun.COM  * set or unset the specified bit.
850*7917SReza.Sabdar@Sun.COM  */
851*7917SReza.Sabdar@Sun.COM static inline int
dbmp_set(dbmap_chunk_t * cp,u_quad_t bn,uint_t * vp)852*7917SReza.Sabdar@Sun.COM dbmp_set(dbmap_chunk_t *cp, u_quad_t bn, uint_t *vp)
853*7917SReza.Sabdar@Sun.COM {
854*7917SReza.Sabdar@Sun.COM 	int rv;
855*7917SReza.Sabdar@Sun.COM 	uint_t mask;
856*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
857*7917SReza.Sabdar@Sun.COM 	uint_t v;
858*7917SReza.Sabdar@Sun.COM 
859*7917SReza.Sabdar@Sun.COM 	bn -= cp->c_off;
860*7917SReza.Sabdar@Sun.COM 	if (bn < cp->c_clen) {
861*7917SReza.Sabdar@Sun.COM 		mask = 1 <<(bn & BMAP_BPW_MASK);
862*7917SReza.Sabdar@Sun.COM 		ip = &cp->c_bmp[bn >> BMAP_BPW_SHIFT];
863*7917SReza.Sabdar@Sun.COM 		v = (*vp <<(bn & BMAP_BPW_MASK)) & mask;
864*7917SReza.Sabdar@Sun.COM 		*ip = (*ip & ~mask) | v;
865*7917SReza.Sabdar@Sun.COM 		BMAP_CSET_DIRTY(cp);
866*7917SReza.Sabdar@Sun.COM 		rv = 0;
867*7917SReza.Sabdar@Sun.COM 	} else
868*7917SReza.Sabdar@Sun.COM 		rv = -ERANGE;
869*7917SReza.Sabdar@Sun.COM 
870*7917SReza.Sabdar@Sun.COM 	return (rv);
871*7917SReza.Sabdar@Sun.COM }
872*7917SReza.Sabdar@Sun.COM 
873*7917SReza.Sabdar@Sun.COM 
874*7917SReza.Sabdar@Sun.COM /*
875*7917SReza.Sabdar@Sun.COM  * dbmp_getlen
876*7917SReza.Sabdar@Sun.COM  *
877*7917SReza.Sabdar@Sun.COM  * Get length of the bitmap.
878*7917SReza.Sabdar@Sun.COM  */
879*7917SReza.Sabdar@Sun.COM static u_quad_t
dbmp_getlen(dbitmap_t * bmp)880*7917SReza.Sabdar@Sun.COM dbmp_getlen(dbitmap_t *bmp)
881*7917SReza.Sabdar@Sun.COM {
882*7917SReza.Sabdar@Sun.COM 	return (bmp ? bmp->bm_len : 0LL);
883*7917SReza.Sabdar@Sun.COM }
884*7917SReza.Sabdar@Sun.COM 
885*7917SReza.Sabdar@Sun.COM 
886*7917SReza.Sabdar@Sun.COM /*
887*7917SReza.Sabdar@Sun.COM  * dbmp_get
888*7917SReza.Sabdar@Sun.COM  *
889*7917SReza.Sabdar@Sun.COM  * Generic function to get bit in a chunk.
890*7917SReza.Sabdar@Sun.COM  */
891*7917SReza.Sabdar@Sun.COM static inline int
dbmp_get(dbmap_chunk_t * cp,u_quad_t bn)892*7917SReza.Sabdar@Sun.COM dbmp_get(dbmap_chunk_t *cp, u_quad_t bn)
893*7917SReza.Sabdar@Sun.COM {
894*7917SReza.Sabdar@Sun.COM 	int rv;
895*7917SReza.Sabdar@Sun.COM 	uint_t bit;
896*7917SReza.Sabdar@Sun.COM 
897*7917SReza.Sabdar@Sun.COM 	bn -= cp->c_off;
898*7917SReza.Sabdar@Sun.COM 	if (bn < cp->c_clen) {
899*7917SReza.Sabdar@Sun.COM 		bit = 1 <<(bn & BMAP_BPW_MASK);
900*7917SReza.Sabdar@Sun.COM 		rv = (cp->c_bmp[bn >> BMAP_BPW_SHIFT] & bit) != 0;
901*7917SReza.Sabdar@Sun.COM 	} else
902*7917SReza.Sabdar@Sun.COM 		rv = -ERANGE;
903*7917SReza.Sabdar@Sun.COM 
904*7917SReza.Sabdar@Sun.COM 	return (rv);
905*7917SReza.Sabdar@Sun.COM }
906*7917SReza.Sabdar@Sun.COM 
907*7917SReza.Sabdar@Sun.COM 
908*7917SReza.Sabdar@Sun.COM /*
909*7917SReza.Sabdar@Sun.COM  * dbm_chunk_seek
910*7917SReza.Sabdar@Sun.COM  *
911*7917SReza.Sabdar@Sun.COM  * Seek in the file where the chunk is saved or should be saved.
912*7917SReza.Sabdar@Sun.COM  */
913*7917SReza.Sabdar@Sun.COM static int
dbm_chunk_seek(dbitmap_t * bmp,u_quad_t bn)914*7917SReza.Sabdar@Sun.COM dbm_chunk_seek(dbitmap_t *bmp, u_quad_t bn)
915*7917SReza.Sabdar@Sun.COM {
916*7917SReza.Sabdar@Sun.COM 	int rv;
917*7917SReza.Sabdar@Sun.COM 	off_t off;
918*7917SReza.Sabdar@Sun.COM 
919*7917SReza.Sabdar@Sun.COM 	if (!bmp)
920*7917SReza.Sabdar@Sun.COM 		rv = -1;
921*7917SReza.Sabdar@Sun.COM 	else {
922*7917SReza.Sabdar@Sun.COM 		off = BMAP_CHUNK_NO(bn) * BMAP_CHUNK_BYTES;
923*7917SReza.Sabdar@Sun.COM 		rv = (lseek(bmp->bm_fd, off, SEEK_SET) != off) ? -1 : 0;
924*7917SReza.Sabdar@Sun.COM 	}
925*7917SReza.Sabdar@Sun.COM 
926*7917SReza.Sabdar@Sun.COM 	return (rv);
927*7917SReza.Sabdar@Sun.COM }
928*7917SReza.Sabdar@Sun.COM 
929*7917SReza.Sabdar@Sun.COM 
930*7917SReza.Sabdar@Sun.COM /*
931*7917SReza.Sabdar@Sun.COM  * dbm_chunk_flush
932*7917SReza.Sabdar@Sun.COM  *
933*7917SReza.Sabdar@Sun.COM  * Save a chunk to file.
934*7917SReza.Sabdar@Sun.COM  */
935*7917SReza.Sabdar@Sun.COM static int
dbm_chunk_flush(dbitmap_t * bmp,dbmap_chunk_t * cp)936*7917SReza.Sabdar@Sun.COM dbm_chunk_flush(dbitmap_t *bmp, dbmap_chunk_t *cp)
937*7917SReza.Sabdar@Sun.COM {
938*7917SReza.Sabdar@Sun.COM 	int rv;
939*7917SReza.Sabdar@Sun.COM 
940*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_flush++;
941*7917SReza.Sabdar@Sun.COM 	if (!bmp || !cp)
942*7917SReza.Sabdar@Sun.COM 		rv = -1;
943*7917SReza.Sabdar@Sun.COM 	else if (dbm_chunk_seek(bmp, cp->c_off) != 0)
944*7917SReza.Sabdar@Sun.COM 		rv = -1;
945*7917SReza.Sabdar@Sun.COM 	else if (write(bmp->bm_fd, cp->c_bmp, cp->c_mlen) != cp->c_mlen)
946*7917SReza.Sabdar@Sun.COM 		rv = -1;
947*7917SReza.Sabdar@Sun.COM 	else
948*7917SReza.Sabdar@Sun.COM 		rv = 0;
949*7917SReza.Sabdar@Sun.COM 
950*7917SReza.Sabdar@Sun.COM 	return (rv);
951*7917SReza.Sabdar@Sun.COM }
952*7917SReza.Sabdar@Sun.COM 
953*7917SReza.Sabdar@Sun.COM 
954*7917SReza.Sabdar@Sun.COM /*
955*7917SReza.Sabdar@Sun.COM  * dbm_chunk_load
956*7917SReza.Sabdar@Sun.COM  *
957*7917SReza.Sabdar@Sun.COM  * Load a chunk from a file.  If the chunk is a new one,
958*7917SReza.Sabdar@Sun.COM  * instead of reading from the disk, the memory for the
959*7917SReza.Sabdar@Sun.COM  * chunk is set to either all zeros or to all ones.
960*7917SReza.Sabdar@Sun.COM  * Otherwise, if the chunk is not a new one, it's read
961*7917SReza.Sabdar@Sun.COM  * from the disk.
962*7917SReza.Sabdar@Sun.COM  *
963*7917SReza.Sabdar@Sun.COM  * The new chunk is positioned in the LRU and hash table
964*7917SReza.Sabdar@Sun.COM  * after its data is ready.
965*7917SReza.Sabdar@Sun.COM  */
966*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
dbm_chunk_load(dbitmap_t * bmp,dbmap_chunk_t * cp,u_quad_t bn,int new)967*7917SReza.Sabdar@Sun.COM dbm_chunk_load(dbitmap_t *bmp, dbmap_chunk_t *cp, u_quad_t bn, int new)
968*7917SReza.Sabdar@Sun.COM {
969*7917SReza.Sabdar@Sun.COM 	int h;
970*7917SReza.Sabdar@Sun.COM 	u_quad_t off, l;
971*7917SReza.Sabdar@Sun.COM 	uint_t cl, ml;
972*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *hp;
973*7917SReza.Sabdar@Sun.COM 
974*7917SReza.Sabdar@Sun.COM 	off = BMAP_CHUNK_OFF(bn);
975*7917SReza.Sabdar@Sun.COM 	l = bmp->bm_len - off;
976*7917SReza.Sabdar@Sun.COM 	if (l >= BMAP_CHUNK_BITS) {
977*7917SReza.Sabdar@Sun.COM 		cl = BMAP_CHUNK_BITS;
978*7917SReza.Sabdar@Sun.COM 		ml = BMAP_CHUNK_BYTES;
979*7917SReza.Sabdar@Sun.COM 	} else {
980*7917SReza.Sabdar@Sun.COM 		cl = l;
981*7917SReza.Sabdar@Sun.COM 		ml = MEM_LEN(l);
982*7917SReza.Sabdar@Sun.COM 	}
983*7917SReza.Sabdar@Sun.COM 
984*7917SReza.Sabdar@Sun.COM 	if (new == BMAP_NEW_CHUNK) {
985*7917SReza.Sabdar@Sun.COM 		if (BMAP_IS_INIT_ONES(bmp))
986*7917SReza.Sabdar@Sun.COM 			(void) memset(cp->c_bmp, 0xff, ml);
987*7917SReza.Sabdar@Sun.COM 		else
988*7917SReza.Sabdar@Sun.COM 			(void) memset(cp->c_bmp, 0x00, ml);
989*7917SReza.Sabdar@Sun.COM 	} else { /* BMAP_OLD_CHUNK */
990*7917SReza.Sabdar@Sun.COM 		if (dbm_chunk_seek(bmp, bn) != 0)
991*7917SReza.Sabdar@Sun.COM 			cp = NULL;
992*7917SReza.Sabdar@Sun.COM 		else if (read(bmp->bm_fd, cp->c_bmp, ml) != ml)
993*7917SReza.Sabdar@Sun.COM 			cp = NULL;
994*7917SReza.Sabdar@Sun.COM 	}
995*7917SReza.Sabdar@Sun.COM 
996*7917SReza.Sabdar@Sun.COM 	if (cp) {
997*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_TAIL(&bmp->bm_lru, cp, c_lru);
998*7917SReza.Sabdar@Sun.COM 		h = HASH(bn);
999*7917SReza.Sabdar@Sun.COM 		hp = &bmp->bm_hash[h];
1000*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_HEAD(hp, cp, c_hash);
1001*7917SReza.Sabdar@Sun.COM 		cp->c_flags = 0;
1002*7917SReza.Sabdar@Sun.COM 		cp->c_off = off;
1003*7917SReza.Sabdar@Sun.COM 		cp->c_clen = cl;
1004*7917SReza.Sabdar@Sun.COM 		cp->c_mlen = ml;
1005*7917SReza.Sabdar@Sun.COM 	}
1006*7917SReza.Sabdar@Sun.COM 
1007*7917SReza.Sabdar@Sun.COM 	return (cp);
1008*7917SReza.Sabdar@Sun.COM }
1009*7917SReza.Sabdar@Sun.COM 
1010*7917SReza.Sabdar@Sun.COM 
1011*7917SReza.Sabdar@Sun.COM /*
1012*7917SReza.Sabdar@Sun.COM  * dbm_chunk_new
1013*7917SReza.Sabdar@Sun.COM  *
1014*7917SReza.Sabdar@Sun.COM  * Create a new chunk and keep track of memory used.
1015*7917SReza.Sabdar@Sun.COM  */
1016*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
dbm_chunk_new(dbitmap_t * bmp,u_quad_t bn)1017*7917SReza.Sabdar@Sun.COM dbm_chunk_new(dbitmap_t *bmp, u_quad_t bn)
1018*7917SReza.Sabdar@Sun.COM {
1019*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1020*7917SReza.Sabdar@Sun.COM 
1021*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_new++;
1022*7917SReza.Sabdar@Sun.COM 	cp = ndmp_malloc(sizeof (dbmap_chunk_t));
1023*7917SReza.Sabdar@Sun.COM 	if (cp) {
1024*7917SReza.Sabdar@Sun.COM 		cp->c_bmp = ndmp_malloc(sizeof (uint_t) * BMAP_CHUNK_WORDS);
1025*7917SReza.Sabdar@Sun.COM 		if (!cp->c_bmp) {
1026*7917SReza.Sabdar@Sun.COM 			free(cp);
1027*7917SReza.Sabdar@Sun.COM 			cp = NULL;
1028*7917SReza.Sabdar@Sun.COM 		} else if (!dbm_chunk_load(bmp, cp, bn, BMAP_NEW_CHUNK)) {
1029*7917SReza.Sabdar@Sun.COM 			free(cp->c_bmp);
1030*7917SReza.Sabdar@Sun.COM 			free(cp);
1031*7917SReza.Sabdar@Sun.COM 			cp = NULL;
1032*7917SReza.Sabdar@Sun.COM 		} else
1033*7917SReza.Sabdar@Sun.COM 			bmp->bm_ccur++;
1034*7917SReza.Sabdar@Sun.COM 	}
1035*7917SReza.Sabdar@Sun.COM 
1036*7917SReza.Sabdar@Sun.COM 	return (cp);
1037*7917SReza.Sabdar@Sun.COM }
1038*7917SReza.Sabdar@Sun.COM 
1039*7917SReza.Sabdar@Sun.COM 
1040*7917SReza.Sabdar@Sun.COM /*
1041*7917SReza.Sabdar@Sun.COM  * dbm_chunk_alloc
1042*7917SReza.Sabdar@Sun.COM  *
1043*7917SReza.Sabdar@Sun.COM  * Allocate a chunk and return it.  If the cache for the
1044*7917SReza.Sabdar@Sun.COM  * chunks is not fully used, a new chunk is created.
1045*7917SReza.Sabdar@Sun.COM  * Otherwise, the first chunk from the LRU list is reclaimed,
1046*7917SReza.Sabdar@Sun.COM  * loaded and returned.
1047*7917SReza.Sabdar@Sun.COM  */
1048*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
dbm_chunk_alloc(dbitmap_t * bmp,u_quad_t bn)1049*7917SReza.Sabdar@Sun.COM dbm_chunk_alloc(dbitmap_t *bmp, u_quad_t bn)
1050*7917SReza.Sabdar@Sun.COM {
1051*7917SReza.Sabdar@Sun.COM 	int h;
1052*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *hp;
1053*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1054*7917SReza.Sabdar@Sun.COM 
1055*7917SReza.Sabdar@Sun.COM 	if (bmp->bm_ccur < bmp->bm_cmax)
1056*7917SReza.Sabdar@Sun.COM 		return (dbm_chunk_new(bmp, bn));
1057*7917SReza.Sabdar@Sun.COM 
1058*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_chunk_reclaim++;
1059*7917SReza.Sabdar@Sun.COM 
1060*7917SReza.Sabdar@Sun.COM 	cp = TAILQ_FIRST(&bmp->bm_lru);
1061*7917SReza.Sabdar@Sun.COM 	if (BMAP_CIS_DIRTY(cp))
1062*7917SReza.Sabdar@Sun.COM 		(void) dbm_chunk_flush(bmp, cp);
1063*7917SReza.Sabdar@Sun.COM 
1064*7917SReza.Sabdar@Sun.COM 	TAILQ_REMOVE(&bmp->bm_lru, cp, c_lru);
1065*7917SReza.Sabdar@Sun.COM 	h = HASH(cp->c_off);
1066*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
1067*7917SReza.Sabdar@Sun.COM 	TAILQ_REMOVE(hp, cp, c_hash);
1068*7917SReza.Sabdar@Sun.COM 	return (dbm_chunk_load(bmp, cp, bn, BMAP_OLD_CHUNK));
1069*7917SReza.Sabdar@Sun.COM }
1070*7917SReza.Sabdar@Sun.COM 
1071*7917SReza.Sabdar@Sun.COM 
1072*7917SReza.Sabdar@Sun.COM /*
1073*7917SReza.Sabdar@Sun.COM  * dbm_chunks_free
1074*7917SReza.Sabdar@Sun.COM  *
1075*7917SReza.Sabdar@Sun.COM  * Release the memory allocated for the chunks.
1076*7917SReza.Sabdar@Sun.COM  */
1077*7917SReza.Sabdar@Sun.COM static void
dbm_chunks_free(dbitmap_t * bmp)1078*7917SReza.Sabdar@Sun.COM dbm_chunks_free(dbitmap_t *bmp)
1079*7917SReza.Sabdar@Sun.COM {
1080*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *headp;
1081*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1082*7917SReza.Sabdar@Sun.COM 
1083*7917SReza.Sabdar@Sun.COM 	if (!bmp)
1084*7917SReza.Sabdar@Sun.COM 		return;
1085*7917SReza.Sabdar@Sun.COM 
1086*7917SReza.Sabdar@Sun.COM 	headp = &bmp->bm_lru;
1087*7917SReza.Sabdar@Sun.COM 	if (!headp)
1088*7917SReza.Sabdar@Sun.COM 		return;
1089*7917SReza.Sabdar@Sun.COM 
1090*7917SReza.Sabdar@Sun.COM 	while (!TAILQ_EMPTY(headp)) {
1091*7917SReza.Sabdar@Sun.COM 		cp = TAILQ_FIRST(headp);
1092*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(headp, cp, c_lru);
1093*7917SReza.Sabdar@Sun.COM 		free(cp->c_bmp);
1094*7917SReza.Sabdar@Sun.COM 		free(cp);
1095*7917SReza.Sabdar@Sun.COM 	}
1096*7917SReza.Sabdar@Sun.COM }
1097*7917SReza.Sabdar@Sun.COM 
1098*7917SReza.Sabdar@Sun.COM 
1099*7917SReza.Sabdar@Sun.COM /*
1100*7917SReza.Sabdar@Sun.COM  * dbm_chunk_reposition
1101*7917SReza.Sabdar@Sun.COM  *
1102*7917SReza.Sabdar@Sun.COM  * Re-position the chunk in the LRU and the hash table.
1103*7917SReza.Sabdar@Sun.COM  */
1104*7917SReza.Sabdar@Sun.COM static void
dbm_chunk_reposition(dbitmap_t * bmp,dbmap_list_t * hp,dbmap_chunk_t * cp)1105*7917SReza.Sabdar@Sun.COM dbm_chunk_reposition(dbitmap_t *bmp, dbmap_list_t *hp, dbmap_chunk_t *cp)
1106*7917SReza.Sabdar@Sun.COM {
1107*7917SReza.Sabdar@Sun.COM 	if (bmp && hp && cp) {
1108*7917SReza.Sabdar@Sun.COM 		TAILQ_REMOVE(&bmp->bm_lru, cp, c_lru);
1109*7917SReza.Sabdar@Sun.COM 		TAILQ_INSERT_TAIL(&bmp->bm_lru, cp, c_lru);
1110*7917SReza.Sabdar@Sun.COM 		if (TAILQ_FIRST(hp) != cp) {
1111*7917SReza.Sabdar@Sun.COM 			TAILQ_REMOVE(hp, cp, c_hash);
1112*7917SReza.Sabdar@Sun.COM 			TAILQ_INSERT_HEAD(hp, cp, c_hash);
1113*7917SReza.Sabdar@Sun.COM 		}
1114*7917SReza.Sabdar@Sun.COM 	}
1115*7917SReza.Sabdar@Sun.COM }
1116*7917SReza.Sabdar@Sun.COM 
1117*7917SReza.Sabdar@Sun.COM 
1118*7917SReza.Sabdar@Sun.COM /*
1119*7917SReza.Sabdar@Sun.COM  * dbm_chunk_find
1120*7917SReza.Sabdar@Sun.COM  *
1121*7917SReza.Sabdar@Sun.COM  * Find and return the chunks which holds the specified bit.
1122*7917SReza.Sabdar@Sun.COM  * Allocate the chunk if necessary and re-position it in the
1123*7917SReza.Sabdar@Sun.COM  * LRU and hash table lists.
1124*7917SReza.Sabdar@Sun.COM  */
1125*7917SReza.Sabdar@Sun.COM static dbmap_chunk_t *
dbm_chunk_find(dbitmap_t * bmp,u_quad_t bn)1126*7917SReza.Sabdar@Sun.COM dbm_chunk_find(dbitmap_t *bmp, u_quad_t bn)
1127*7917SReza.Sabdar@Sun.COM {
1128*7917SReza.Sabdar@Sun.COM 	int h;
1129*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1130*7917SReza.Sabdar@Sun.COM 	dbmap_list_t *hp;
1131*7917SReza.Sabdar@Sun.COM 
1132*7917SReza.Sabdar@Sun.COM 	if (!bmp)
1133*7917SReza.Sabdar@Sun.COM 		return (NULL);
1134*7917SReza.Sabdar@Sun.COM 
1135*7917SReza.Sabdar@Sun.COM 	h = HASH(bn);
1136*7917SReza.Sabdar@Sun.COM 	hp = &bmp->bm_hash[h];
1137*7917SReza.Sabdar@Sun.COM 	TAILQ_FOREACH(cp, hp, c_hash) {
1138*7917SReza.Sabdar@Sun.COM 		if (bn >= cp->c_off && bn < (cp->c_off + cp->c_clen)) {
1139*7917SReza.Sabdar@Sun.COM 			bitmap_stats.bs_cache_hit++;
1140*7917SReza.Sabdar@Sun.COM 
1141*7917SReza.Sabdar@Sun.COM 			dbm_chunk_reposition(bmp, hp, cp);
1142*7917SReza.Sabdar@Sun.COM 			return (cp);
1143*7917SReza.Sabdar@Sun.COM 		}
1144*7917SReza.Sabdar@Sun.COM 	}
1145*7917SReza.Sabdar@Sun.COM 
1146*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_cache_miss++;
1147*7917SReza.Sabdar@Sun.COM 
1148*7917SReza.Sabdar@Sun.COM 	return (dbm_chunk_alloc(bmp, bn));
1149*7917SReza.Sabdar@Sun.COM }
1150*7917SReza.Sabdar@Sun.COM 
1151*7917SReza.Sabdar@Sun.COM 
1152*7917SReza.Sabdar@Sun.COM /*
1153*7917SReza.Sabdar@Sun.COM  * dbmp_setval
1154*7917SReza.Sabdar@Sun.COM  *
1155*7917SReza.Sabdar@Sun.COM  * Set a range of bits in the bitmap specified by the
1156*7917SReza.Sabdar@Sun.COM  * vector.
1157*7917SReza.Sabdar@Sun.COM  */
1158*7917SReza.Sabdar@Sun.COM static int
dbmp_setval(dbitmap_t * bmp,bm_iovec_t * vp)1159*7917SReza.Sabdar@Sun.COM dbmp_setval(dbitmap_t *bmp, bm_iovec_t *vp)
1160*7917SReza.Sabdar@Sun.COM {
1161*7917SReza.Sabdar@Sun.COM 	int rv;
1162*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
1163*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
1164*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
1165*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1166*7917SReza.Sabdar@Sun.COM 
1167*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
1168*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
1169*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
1170*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
1171*7917SReza.Sabdar@Sun.COM 
1172*7917SReza.Sabdar@Sun.COM 	if (*vp->bmv_val) {
1173*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set++;
1174*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_set_bits += vp->bmv_len;
1175*7917SReza.Sabdar@Sun.COM 	} else {
1176*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset++;
1177*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_unset_bits += vp->bmv_len;
1178*7917SReza.Sabdar@Sun.COM 	}
1179*7917SReza.Sabdar@Sun.COM 
1180*7917SReza.Sabdar@Sun.COM 	do {
1181*7917SReza.Sabdar@Sun.COM 		cp = dbm_chunk_find(bmp, bn);
1182*7917SReza.Sabdar@Sun.COM 		if (!cp)
1183*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
1184*7917SReza.Sabdar@Sun.COM 
1185*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
1186*7917SReza.Sabdar@Sun.COM 			rv = dbmp_set(cp, bn, vp->bmv_val);
1187*7917SReza.Sabdar@Sun.COM 			if (rv != 0)
1188*7917SReza.Sabdar@Sun.COM 				return (rv);
1189*7917SReza.Sabdar@Sun.COM 		}
1190*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
1191*7917SReza.Sabdar@Sun.COM 
1192*7917SReza.Sabdar@Sun.COM 	return (0);
1193*7917SReza.Sabdar@Sun.COM }
1194*7917SReza.Sabdar@Sun.COM 
1195*7917SReza.Sabdar@Sun.COM 
1196*7917SReza.Sabdar@Sun.COM /*
1197*7917SReza.Sabdar@Sun.COM  * dbmp_getval
1198*7917SReza.Sabdar@Sun.COM  *
1199*7917SReza.Sabdar@Sun.COM  * Get a range of bits in the bitmap specified by the
1200*7917SReza.Sabdar@Sun.COM  * vector.
1201*7917SReza.Sabdar@Sun.COM  */
1202*7917SReza.Sabdar@Sun.COM static int
dbmp_getval(dbitmap_t * bmp,bm_iovec_t * vp)1203*7917SReza.Sabdar@Sun.COM dbmp_getval(dbitmap_t *bmp, bm_iovec_t *vp)
1204*7917SReza.Sabdar@Sun.COM {
1205*7917SReza.Sabdar@Sun.COM 	uint_t cnt;
1206*7917SReza.Sabdar@Sun.COM 	uint_t *ip;
1207*7917SReza.Sabdar@Sun.COM 	int rv;
1208*7917SReza.Sabdar@Sun.COM 	u_quad_t cl;
1209*7917SReza.Sabdar@Sun.COM 	u_quad_t bn;
1210*7917SReza.Sabdar@Sun.COM 	u_quad_t max;
1211*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1212*7917SReza.Sabdar@Sun.COM 
1213*7917SReza.Sabdar@Sun.COM 	bn = vp->bmv_base;
1214*7917SReza.Sabdar@Sun.COM 	max = bn + vp->bmv_len;
1215*7917SReza.Sabdar@Sun.COM 	if (bn >= bmp->bm_len || max > bmp->bm_len)
1216*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
1217*7917SReza.Sabdar@Sun.COM 
1218*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get++;
1219*7917SReza.Sabdar@Sun.COM 	bitmap_stats.bs_get_bits += 1;
1220*7917SReza.Sabdar@Sun.COM 
1221*7917SReza.Sabdar@Sun.COM 	cnt = 0;
1222*7917SReza.Sabdar@Sun.COM 	ip = vp->bmv_val;
1223*7917SReza.Sabdar@Sun.COM 	*ip = 0;
1224*7917SReza.Sabdar@Sun.COM 	do {
1225*7917SReza.Sabdar@Sun.COM 		cp = dbm_chunk_find(bmp, bn);
1226*7917SReza.Sabdar@Sun.COM 		if (!cp)
1227*7917SReza.Sabdar@Sun.COM 			return (-ERANGE);
1228*7917SReza.Sabdar@Sun.COM 
1229*7917SReza.Sabdar@Sun.COM 		for (cl = cp->c_off + cp->c_clen; bn < cl && bn < max; bn++) {
1230*7917SReza.Sabdar@Sun.COM 			rv = dbmp_get(cp, bn);
1231*7917SReza.Sabdar@Sun.COM 			if (rv < 0)
1232*7917SReza.Sabdar@Sun.COM 				return (rv);
1233*7917SReza.Sabdar@Sun.COM 
1234*7917SReza.Sabdar@Sun.COM 			*ip |= rv << cnt;
1235*7917SReza.Sabdar@Sun.COM 			if (++cnt >= BMAP_BPW) {
1236*7917SReza.Sabdar@Sun.COM 				*++ip = 0;
1237*7917SReza.Sabdar@Sun.COM 				cnt = 0;
1238*7917SReza.Sabdar@Sun.COM 			}
1239*7917SReza.Sabdar@Sun.COM 		}
1240*7917SReza.Sabdar@Sun.COM 	} while (bn < max);
1241*7917SReza.Sabdar@Sun.COM 
1242*7917SReza.Sabdar@Sun.COM 	return (0);
1243*7917SReza.Sabdar@Sun.COM }
1244*7917SReza.Sabdar@Sun.COM 
1245*7917SReza.Sabdar@Sun.COM 
1246*7917SReza.Sabdar@Sun.COM /*
1247*7917SReza.Sabdar@Sun.COM  * dbyte_apply_ifset
1248*7917SReza.Sabdar@Sun.COM  *
1249*7917SReza.Sabdar@Sun.COM  * Apply the function on the set bits of the specified word.
1250*7917SReza.Sabdar@Sun.COM  */
1251*7917SReza.Sabdar@Sun.COM static int
dbyte_apply_ifset(dbitmap_t * bmp,u_quad_t off,uint_t b,int (* fp)(),void * arg)1252*7917SReza.Sabdar@Sun.COM dbyte_apply_ifset(dbitmap_t *bmp, u_quad_t off, uint_t b, int(*fp)(),
1253*7917SReza.Sabdar@Sun.COM     void *arg)
1254*7917SReza.Sabdar@Sun.COM {
1255*7917SReza.Sabdar@Sun.COM 	int bmd;
1256*7917SReza.Sabdar@Sun.COM 	int rv;
1257*7917SReza.Sabdar@Sun.COM 	u_quad_t l;
1258*7917SReza.Sabdar@Sun.COM 
1259*7917SReza.Sabdar@Sun.COM 	rv = 0;
1260*7917SReza.Sabdar@Sun.COM 	l = dbmp_getlen(bmp);
1261*7917SReza.Sabdar@Sun.COM 	bmd = dbmp2bmd(bmp);
1262*7917SReza.Sabdar@Sun.COM 	for (; b && off < l; off++) {
1263*7917SReza.Sabdar@Sun.COM 		if (b & 1) {
1264*7917SReza.Sabdar@Sun.COM 			bitmap_stats.bs_set_applied++;
1265*7917SReza.Sabdar@Sun.COM 
1266*7917SReza.Sabdar@Sun.COM 			if ((rv = (*fp)(bmd, off, arg)))
1267*7917SReza.Sabdar@Sun.COM 				break;
1268*7917SReza.Sabdar@Sun.COM 		}
1269*7917SReza.Sabdar@Sun.COM 		b >>= 1;
1270*7917SReza.Sabdar@Sun.COM 	}
1271*7917SReza.Sabdar@Sun.COM 
1272*7917SReza.Sabdar@Sun.COM 	return (rv);
1273*7917SReza.Sabdar@Sun.COM }
1274*7917SReza.Sabdar@Sun.COM 
1275*7917SReza.Sabdar@Sun.COM 
1276*7917SReza.Sabdar@Sun.COM /*
1277*7917SReza.Sabdar@Sun.COM  * dbm_chunk_apply_ifset
1278*7917SReza.Sabdar@Sun.COM  *
1279*7917SReza.Sabdar@Sun.COM  * Apply the function on the set bits of the specified chunk.
1280*7917SReza.Sabdar@Sun.COM  */
1281*7917SReza.Sabdar@Sun.COM static int
dbm_chunk_apply_ifset(dbitmap_t * bmp,dbmap_chunk_t * cp,int (* fp)(),void * arg)1282*7917SReza.Sabdar@Sun.COM dbm_chunk_apply_ifset(dbitmap_t *bmp, dbmap_chunk_t *cp, int(*fp)(),
1283*7917SReza.Sabdar@Sun.COM     void *arg)
1284*7917SReza.Sabdar@Sun.COM {
1285*7917SReza.Sabdar@Sun.COM 	int rv;
1286*7917SReza.Sabdar@Sun.COM 	uint_t *bp;
1287*7917SReza.Sabdar@Sun.COM 	uint_t i, m;
1288*7917SReza.Sabdar@Sun.COM 	u_quad_t q;
1289*7917SReza.Sabdar@Sun.COM 
1290*7917SReza.Sabdar@Sun.COM 	rv = 0;
1291*7917SReza.Sabdar@Sun.COM 	bp = cp->c_bmp;
1292*7917SReza.Sabdar@Sun.COM 	q = cp->c_off;
1293*7917SReza.Sabdar@Sun.COM 	m = cp->c_mlen / BMAP_WSIZE;
1294*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < m; q += BMAP_BPW, bp++, i++)
1295*7917SReza.Sabdar@Sun.COM 		if (*bp) {
1296*7917SReza.Sabdar@Sun.COM 			rv = dbyte_apply_ifset(bmp, q, *bp, fp, arg);
1297*7917SReza.Sabdar@Sun.COM 			if (rv != 0)
1298*7917SReza.Sabdar@Sun.COM 				break;
1299*7917SReza.Sabdar@Sun.COM 		}
1300*7917SReza.Sabdar@Sun.COM 
1301*7917SReza.Sabdar@Sun.COM 	return (rv);
1302*7917SReza.Sabdar@Sun.COM }
1303*7917SReza.Sabdar@Sun.COM 
1304*7917SReza.Sabdar@Sun.COM 
1305*7917SReza.Sabdar@Sun.COM /*
1306*7917SReza.Sabdar@Sun.COM  * swfile_trunc
1307*7917SReza.Sabdar@Sun.COM  *
1308*7917SReza.Sabdar@Sun.COM  * Truncate the rest of the swap file.
1309*7917SReza.Sabdar@Sun.COM  */
1310*7917SReza.Sabdar@Sun.COM static int
swfile_trunc(int fd)1311*7917SReza.Sabdar@Sun.COM swfile_trunc(int fd)
1312*7917SReza.Sabdar@Sun.COM {
1313*7917SReza.Sabdar@Sun.COM 	int rv;
1314*7917SReza.Sabdar@Sun.COM 	off_t off;
1315*7917SReza.Sabdar@Sun.COM 
1316*7917SReza.Sabdar@Sun.COM 	/*
1317*7917SReza.Sabdar@Sun.COM 	 * Get the current offset and truncate whatever is
1318*7917SReza.Sabdar@Sun.COM 	 * after this point.
1319*7917SReza.Sabdar@Sun.COM 	 */
1320*7917SReza.Sabdar@Sun.COM 	rv = 0;
1321*7917SReza.Sabdar@Sun.COM 	if ((off = lseek(fd, 0, SEEK_CUR)) < 0)
1322*7917SReza.Sabdar@Sun.COM 		rv = -1;
1323*7917SReza.Sabdar@Sun.COM 	else if (ftruncate(fd, off) != 0)
1324*7917SReza.Sabdar@Sun.COM 		rv = -1;
1325*7917SReza.Sabdar@Sun.COM 
1326*7917SReza.Sabdar@Sun.COM 	return (rv);
1327*7917SReza.Sabdar@Sun.COM }
1328*7917SReza.Sabdar@Sun.COM 
1329*7917SReza.Sabdar@Sun.COM 
1330*7917SReza.Sabdar@Sun.COM /*
1331*7917SReza.Sabdar@Sun.COM  * swfile_init
1332*7917SReza.Sabdar@Sun.COM  *
1333*7917SReza.Sabdar@Sun.COM  * Initialize the swap file.  The necessary disk space is
1334*7917SReza.Sabdar@Sun.COM  * reserved by writing to the swap file for swapping the
1335*7917SReza.Sabdar@Sun.COM  * chunks in/out of the file.
1336*7917SReza.Sabdar@Sun.COM  */
1337*7917SReza.Sabdar@Sun.COM static int
swfile_init(int fd,u_quad_t len,int set)1338*7917SReza.Sabdar@Sun.COM swfile_init(int fd, u_quad_t len, int set)
1339*7917SReza.Sabdar@Sun.COM {
1340*7917SReza.Sabdar@Sun.COM 	u_quad_t i, n;
1341*7917SReza.Sabdar@Sun.COM 	uint_t cl, ml;
1342*7917SReza.Sabdar@Sun.COM 	uint_t buf[BMAP_CHUNK_WORDS];
1343*7917SReza.Sabdar@Sun.COM 
1344*7917SReza.Sabdar@Sun.COM 	(void) memset(buf, set ? 0xff : 0x00, BMAP_CHUNK_BYTES);
1345*7917SReza.Sabdar@Sun.COM 	n = len / BMAP_CHUNK_BITS;
1346*7917SReza.Sabdar@Sun.COM 	for (i = 0; i < n; i++)
1347*7917SReza.Sabdar@Sun.COM 		if (write(fd, buf, BMAP_CHUNK_BYTES) != BMAP_CHUNK_BYTES)
1348*7917SReza.Sabdar@Sun.COM 			return (-1);
1349*7917SReza.Sabdar@Sun.COM 
1350*7917SReza.Sabdar@Sun.COM 	cl = (uint_t)(len % BMAP_CHUNK_BITS);
1351*7917SReza.Sabdar@Sun.COM 	ml = MEM_LEN(cl);
1352*7917SReza.Sabdar@Sun.COM 	if (write(fd, buf, ml) != ml)
1353*7917SReza.Sabdar@Sun.COM 		return (-1);
1354*7917SReza.Sabdar@Sun.COM 
1355*7917SReza.Sabdar@Sun.COM 	return (swfile_trunc(fd));
1356*7917SReza.Sabdar@Sun.COM }
1357*7917SReza.Sabdar@Sun.COM 
1358*7917SReza.Sabdar@Sun.COM 
1359*7917SReza.Sabdar@Sun.COM /*
1360*7917SReza.Sabdar@Sun.COM  * dbm_alloc
1361*7917SReza.Sabdar@Sun.COM  *
1362*7917SReza.Sabdar@Sun.COM  * Allocate a bit map and return a handle to it.
1363*7917SReza.Sabdar@Sun.COM  *
1364*7917SReza.Sabdar@Sun.COM  * The swap file is created if it does not exist.
1365*7917SReza.Sabdar@Sun.COM  * The file is truncated if it exists and is larger
1366*7917SReza.Sabdar@Sun.COM  * than needed amount.
1367*7917SReza.Sabdar@Sun.COM  *
1368*7917SReza.Sabdar@Sun.COM  * The hash table and LRU list are empty at this point.
1369*7917SReza.Sabdar@Sun.COM  * They are allocated and/or loaded on-demand.
1370*7917SReza.Sabdar@Sun.COM  */
1371*7917SReza.Sabdar@Sun.COM int
dbm_alloc(char * fname,u_quad_t len,int set)1372*7917SReza.Sabdar@Sun.COM dbm_alloc(char *fname, u_quad_t len, int set)
1373*7917SReza.Sabdar@Sun.COM {
1374*7917SReza.Sabdar@Sun.COM 	int fd;
1375*7917SReza.Sabdar@Sun.COM 	int bmd;
1376*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1377*7917SReza.Sabdar@Sun.COM 
1378*7917SReza.Sabdar@Sun.COM 	if (!fname || !*fname || !len)
1379*7917SReza.Sabdar@Sun.COM 		return (-1);
1380*7917SReza.Sabdar@Sun.COM 
1381*7917SReza.Sabdar@Sun.COM 	/*
1382*7917SReza.Sabdar@Sun.COM 	 * When allocating bitmap, make sure there is enough
1383*7917SReza.Sabdar@Sun.COM 	 * disk space by allocating needed disk space, for
1384*7917SReza.Sabdar@Sun.COM 	 * writing back the dirty chunks when swaping them out.
1385*7917SReza.Sabdar@Sun.COM 	 */
1386*7917SReza.Sabdar@Sun.COM 	bmd = dbmd_alloc();
1387*7917SReza.Sabdar@Sun.COM 	if (bmd < 0)
1388*7917SReza.Sabdar@Sun.COM 		return (bmd);
1389*7917SReza.Sabdar@Sun.COM 
1390*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1391*7917SReza.Sabdar@Sun.COM 	if ((fd = open(fname, O_RDWR|O_CREAT, 0600)) < 0)
1392*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1393*7917SReza.Sabdar@Sun.COM 	else if (swfile_init(fd, len, set) < 0) {
1394*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1395*7917SReza.Sabdar@Sun.COM 		(void) close(fd);
1396*7917SReza.Sabdar@Sun.COM 		(void) unlink(fname);
1397*7917SReza.Sabdar@Sun.COM 		dbmd_free(bmd);
1398*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1399*7917SReza.Sabdar@Sun.COM 	} else if (!(bmp->bm_fname = strdup(fname))) {
1400*7917SReza.Sabdar@Sun.COM 		(void) close(fd);
1401*7917SReza.Sabdar@Sun.COM 		(void) unlink(fname);
1402*7917SReza.Sabdar@Sun.COM 		dbmd_free(bmd);
1403*7917SReza.Sabdar@Sun.COM 		bmd = -1;
1404*7917SReza.Sabdar@Sun.COM 	} else {
1405*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_alloc_cnt++;
1406*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_alloc_size += len;
1407*7917SReza.Sabdar@Sun.COM 
1408*7917SReza.Sabdar@Sun.COM 		bmp->bm_fd = fd;
1409*7917SReza.Sabdar@Sun.COM 		if (set)
1410*7917SReza.Sabdar@Sun.COM 			BMAP_SET_FLAGS(bmp, BMAP_BINIT_ONES);
1411*7917SReza.Sabdar@Sun.COM 		else
1412*7917SReza.Sabdar@Sun.COM 			BMAP_UNSET_FLAGS(bmp, BMAP_BINIT_ONES);
1413*7917SReza.Sabdar@Sun.COM 		bmp->bm_len = len;
1414*7917SReza.Sabdar@Sun.COM 		bmp->bm_ccur = 0;
1415*7917SReza.Sabdar@Sun.COM 		bmp->bm_cmax = BMAP_CHUNK_MAX;
1416*7917SReza.Sabdar@Sun.COM 		TAILQ_INIT(&bmp->bm_lru);
1417*7917SReza.Sabdar@Sun.COM 		hash_init((bmap_list_t *)bmp->bm_hash);
1418*7917SReza.Sabdar@Sun.COM 	}
1419*7917SReza.Sabdar@Sun.COM 
1420*7917SReza.Sabdar@Sun.COM 	return (bmd);
1421*7917SReza.Sabdar@Sun.COM }
1422*7917SReza.Sabdar@Sun.COM 
1423*7917SReza.Sabdar@Sun.COM 
1424*7917SReza.Sabdar@Sun.COM /*
1425*7917SReza.Sabdar@Sun.COM  * dbm_free
1426*7917SReza.Sabdar@Sun.COM  *
1427*7917SReza.Sabdar@Sun.COM  * Free memory allocated for the bitmap and remove its swap file.
1428*7917SReza.Sabdar@Sun.COM  */
1429*7917SReza.Sabdar@Sun.COM int
dbm_free(int bmd)1430*7917SReza.Sabdar@Sun.COM dbm_free(int bmd)
1431*7917SReza.Sabdar@Sun.COM {
1432*7917SReza.Sabdar@Sun.COM 	int rv;
1433*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1434*7917SReza.Sabdar@Sun.COM 
1435*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1436*7917SReza.Sabdar@Sun.COM 	if (bmp && BMAP_IS_INUSE(bmp)) {
1437*7917SReza.Sabdar@Sun.COM 		bitmap_stats.bs_free_cnt++;
1438*7917SReza.Sabdar@Sun.COM 
1439*7917SReza.Sabdar@Sun.COM 		dbm_chunks_free(bmp);
1440*7917SReza.Sabdar@Sun.COM 		(void) close(bmp->bm_fd);
1441*7917SReza.Sabdar@Sun.COM 		(void) unlink(bmp->bm_fname);
1442*7917SReza.Sabdar@Sun.COM 		free(bmp->bm_fname);
1443*7917SReza.Sabdar@Sun.COM 		dbmd_free(bmd);
1444*7917SReza.Sabdar@Sun.COM 		rv = 0;
1445*7917SReza.Sabdar@Sun.COM 	} else
1446*7917SReza.Sabdar@Sun.COM 		rv = -1;
1447*7917SReza.Sabdar@Sun.COM 
1448*7917SReza.Sabdar@Sun.COM 	return (rv);
1449*7917SReza.Sabdar@Sun.COM }
1450*7917SReza.Sabdar@Sun.COM 
1451*7917SReza.Sabdar@Sun.COM 
1452*7917SReza.Sabdar@Sun.COM /*
1453*7917SReza.Sabdar@Sun.COM  * dbm_getlen
1454*7917SReza.Sabdar@Sun.COM  *
1455*7917SReza.Sabdar@Sun.COM  * Return length of the bitmap.
1456*7917SReza.Sabdar@Sun.COM  */
1457*7917SReza.Sabdar@Sun.COM u_quad_t
dbm_getlen(int bmd)1458*7917SReza.Sabdar@Sun.COM dbm_getlen(int bmd)
1459*7917SReza.Sabdar@Sun.COM {
1460*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1461*7917SReza.Sabdar@Sun.COM 
1462*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1463*7917SReza.Sabdar@Sun.COM 	return (dbmp_getlen(bmp));
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_set
1469*7917SReza.Sabdar@Sun.COM  *
1470*7917SReza.Sabdar@Sun.COM  * Set a range of bits.
1471*7917SReza.Sabdar@Sun.COM  */
1472*7917SReza.Sabdar@Sun.COM int
dbm_set(int bmd,u_quad_t start,u_quad_t len,uint_t val)1473*7917SReza.Sabdar@Sun.COM dbm_set(int bmd, u_quad_t start, u_quad_t len, uint_t val)
1474*7917SReza.Sabdar@Sun.COM {
1475*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1476*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1477*7917SReza.Sabdar@Sun.COM 
1478*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1479*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1480*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = &val;
1481*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1482*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1483*7917SReza.Sabdar@Sun.COM 
1484*7917SReza.Sabdar@Sun.COM 	return (dbm_setiov(bmd, &io));
1485*7917SReza.Sabdar@Sun.COM }
1486*7917SReza.Sabdar@Sun.COM 
1487*7917SReza.Sabdar@Sun.COM 
1488*7917SReza.Sabdar@Sun.COM /*
1489*7917SReza.Sabdar@Sun.COM  * dbm_getiov
1490*7917SReza.Sabdar@Sun.COM  *
1491*7917SReza.Sabdar@Sun.COM  * Get bits specified by the array of vectors.
1492*7917SReza.Sabdar@Sun.COM  */
1493*7917SReza.Sabdar@Sun.COM int
dbm_getiov(int bmd,bm_io_t * iop)1494*7917SReza.Sabdar@Sun.COM dbm_getiov(int bmd, bm_io_t *iop)
1495*7917SReza.Sabdar@Sun.COM {
1496*7917SReza.Sabdar@Sun.COM 	int i;
1497*7917SReza.Sabdar@Sun.COM 	int rv;
1498*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
1499*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1500*7917SReza.Sabdar@Sun.COM 
1501*7917SReza.Sabdar@Sun.COM 	if (!iop)
1502*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1503*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2dbmp(bmd)))
1504*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1505*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
1506*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1507*7917SReza.Sabdar@Sun.COM 	else {
1508*7917SReza.Sabdar@Sun.COM 		rv = 0;
1509*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
1510*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++) {
1511*7917SReza.Sabdar@Sun.COM 			if (!vp)
1512*7917SReza.Sabdar@Sun.COM 				return (-EINVAL);
1513*7917SReza.Sabdar@Sun.COM 			rv |= dbmp_getval(bmp, vp);
1514*7917SReza.Sabdar@Sun.COM 		}
1515*7917SReza.Sabdar@Sun.COM 	}
1516*7917SReza.Sabdar@Sun.COM 
1517*7917SReza.Sabdar@Sun.COM 	return (rv);
1518*7917SReza.Sabdar@Sun.COM }
1519*7917SReza.Sabdar@Sun.COM 
1520*7917SReza.Sabdar@Sun.COM 
1521*7917SReza.Sabdar@Sun.COM /*
1522*7917SReza.Sabdar@Sun.COM  * dbm_setiov
1523*7917SReza.Sabdar@Sun.COM  *
1524*7917SReza.Sabdar@Sun.COM  * Set bits specified by the array of vectors.
1525*7917SReza.Sabdar@Sun.COM  */
1526*7917SReza.Sabdar@Sun.COM int
dbm_setiov(int bmd,bm_io_t * iop)1527*7917SReza.Sabdar@Sun.COM dbm_setiov(int bmd, bm_io_t *iop)
1528*7917SReza.Sabdar@Sun.COM {
1529*7917SReza.Sabdar@Sun.COM 	int i;
1530*7917SReza.Sabdar@Sun.COM 	int rv;
1531*7917SReza.Sabdar@Sun.COM 	bm_iovec_t *vp;
1532*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1533*7917SReza.Sabdar@Sun.COM 
1534*7917SReza.Sabdar@Sun.COM 	if (!iop)
1535*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1536*7917SReza.Sabdar@Sun.COM 	else if (!(bmp = bmd2dbmp(bmd)))
1537*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1538*7917SReza.Sabdar@Sun.COM 	else if (iop->bmio_iovcnt <= 0)
1539*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1540*7917SReza.Sabdar@Sun.COM 	else if (!iop->bmio_iov)
1541*7917SReza.Sabdar@Sun.COM 		rv = -EINVAL;
1542*7917SReza.Sabdar@Sun.COM 	else {
1543*7917SReza.Sabdar@Sun.COM 		rv = 0;
1544*7917SReza.Sabdar@Sun.COM 		vp = iop->bmio_iov;
1545*7917SReza.Sabdar@Sun.COM 		for (i = 0; i < iop->bmio_iovcnt; vp++, i++)
1546*7917SReza.Sabdar@Sun.COM 			rv |= dbmp_setval(bmp, vp);
1547*7917SReza.Sabdar@Sun.COM 	}
1548*7917SReza.Sabdar@Sun.COM 
1549*7917SReza.Sabdar@Sun.COM 	return (rv);
1550*7917SReza.Sabdar@Sun.COM }
1551*7917SReza.Sabdar@Sun.COM 
1552*7917SReza.Sabdar@Sun.COM 
1553*7917SReza.Sabdar@Sun.COM /*
1554*7917SReza.Sabdar@Sun.COM  * dbm_apply_ifset
1555*7917SReza.Sabdar@Sun.COM  *
1556*7917SReza.Sabdar@Sun.COM  * Call the callback function for each set bit in the bitmap and
1557*7917SReza.Sabdar@Sun.COM  * pass the 'arg' and bit number as its argument.
1558*7917SReza.Sabdar@Sun.COM  */
1559*7917SReza.Sabdar@Sun.COM int
dbm_apply_ifset(int bmd,int (* fp)(),void * arg)1560*7917SReza.Sabdar@Sun.COM dbm_apply_ifset(int bmd, int(*fp)(), void *arg)
1561*7917SReza.Sabdar@Sun.COM {
1562*7917SReza.Sabdar@Sun.COM 	int rv;
1563*7917SReza.Sabdar@Sun.COM 	u_quad_t q;
1564*7917SReza.Sabdar@Sun.COM 	dbitmap_t *bmp;
1565*7917SReza.Sabdar@Sun.COM 	dbmap_chunk_t *cp;
1566*7917SReza.Sabdar@Sun.COM 
1567*7917SReza.Sabdar@Sun.COM 	bmp = bmd2dbmp(bmd);
1568*7917SReza.Sabdar@Sun.COM 	if (!bmp || !fp)
1569*7917SReza.Sabdar@Sun.COM 		return (-EINVAL);
1570*7917SReza.Sabdar@Sun.COM 
1571*7917SReza.Sabdar@Sun.COM 	rv = 0;
1572*7917SReza.Sabdar@Sun.COM 	for (q = 0; q < bmp->bm_len; q += BMAP_CHUNK_BITS) {
1573*7917SReza.Sabdar@Sun.COM 		cp = dbm_chunk_find(bmp, q);
1574*7917SReza.Sabdar@Sun.COM 		if (!cp) {
1575*7917SReza.Sabdar@Sun.COM 			rv = -ERANGE;
1576*7917SReza.Sabdar@Sun.COM 			break;
1577*7917SReza.Sabdar@Sun.COM 		}
1578*7917SReza.Sabdar@Sun.COM 
1579*7917SReza.Sabdar@Sun.COM 		rv = dbm_chunk_apply_ifset(bmp, cp, fp, arg);
1580*7917SReza.Sabdar@Sun.COM 		if (rv != 0)
1581*7917SReza.Sabdar@Sun.COM 			break;
1582*7917SReza.Sabdar@Sun.COM 	}
1583*7917SReza.Sabdar@Sun.COM 
1584*7917SReza.Sabdar@Sun.COM 	return (rv);
1585*7917SReza.Sabdar@Sun.COM }
1586*7917SReza.Sabdar@Sun.COM 
1587*7917SReza.Sabdar@Sun.COM 
1588*7917SReza.Sabdar@Sun.COM /*
1589*7917SReza.Sabdar@Sun.COM  * bm_set
1590*7917SReza.Sabdar@Sun.COM  *
1591*7917SReza.Sabdar@Sun.COM  * Set a range of bits.
1592*7917SReza.Sabdar@Sun.COM  */
1593*7917SReza.Sabdar@Sun.COM int
bm_set(int bmd,u_quad_t start,u_quad_t len,uint_t val)1594*7917SReza.Sabdar@Sun.COM bm_set(int bmd, u_quad_t start, u_quad_t len, uint_t val)
1595*7917SReza.Sabdar@Sun.COM {
1596*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1597*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1598*7917SReza.Sabdar@Sun.COM 
1599*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1600*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1601*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = &val;
1602*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1603*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1604*7917SReza.Sabdar@Sun.COM 
1605*7917SReza.Sabdar@Sun.COM 	return (bm_setiov(bmd, &io));
1606*7917SReza.Sabdar@Sun.COM }
1607*7917SReza.Sabdar@Sun.COM 
1608*7917SReza.Sabdar@Sun.COM 
1609*7917SReza.Sabdar@Sun.COM /*
1610*7917SReza.Sabdar@Sun.COM  * bm_get
1611*7917SReza.Sabdar@Sun.COM  *
1612*7917SReza.Sabdar@Sun.COM  * Get a range of bits.
1613*7917SReza.Sabdar@Sun.COM  */
1614*7917SReza.Sabdar@Sun.COM int
bm_get(int bmd,u_quad_t start,u_quad_t len,uint_t * buf)1615*7917SReza.Sabdar@Sun.COM bm_get(int bmd, u_quad_t start, u_quad_t len, uint_t *buf)
1616*7917SReza.Sabdar@Sun.COM {
1617*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1618*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1619*7917SReza.Sabdar@Sun.COM 
1620*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1621*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1622*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = buf;
1623*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1624*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1625*7917SReza.Sabdar@Sun.COM 
1626*7917SReza.Sabdar@Sun.COM 	return (bm_getiov(bmd, &io));
1627*7917SReza.Sabdar@Sun.COM }
1628*7917SReza.Sabdar@Sun.COM 
1629*7917SReza.Sabdar@Sun.COM 
1630*7917SReza.Sabdar@Sun.COM /*
1631*7917SReza.Sabdar@Sun.COM  * bm_getone
1632*7917SReza.Sabdar@Sun.COM  *
1633*7917SReza.Sabdar@Sun.COM  * Get only one bit.
1634*7917SReza.Sabdar@Sun.COM  */
1635*7917SReza.Sabdar@Sun.COM int
bm_getone(int bmd,u_quad_t bitnum)1636*7917SReza.Sabdar@Sun.COM bm_getone(int bmd, u_quad_t bitnum)
1637*7917SReza.Sabdar@Sun.COM {
1638*7917SReza.Sabdar@Sun.COM 	uint_t i;
1639*7917SReza.Sabdar@Sun.COM 
1640*7917SReza.Sabdar@Sun.COM 	if (bm_get(bmd, bitnum, 1, &i) == 0)
1641*7917SReza.Sabdar@Sun.COM 		return (i ? 1 : 0);
1642*7917SReza.Sabdar@Sun.COM 
1643*7917SReza.Sabdar@Sun.COM 	return (0);
1644*7917SReza.Sabdar@Sun.COM }
1645*7917SReza.Sabdar@Sun.COM 
1646*7917SReza.Sabdar@Sun.COM 
1647*7917SReza.Sabdar@Sun.COM /*
1648*7917SReza.Sabdar@Sun.COM  * dbm_get
1649*7917SReza.Sabdar@Sun.COM  *
1650*7917SReza.Sabdar@Sun.COM  * Get a range of bits.
1651*7917SReza.Sabdar@Sun.COM  */
1652*7917SReza.Sabdar@Sun.COM int
dbm_get(int bmd,u_quad_t start,u_quad_t len,uint_t * buf)1653*7917SReza.Sabdar@Sun.COM dbm_get(int bmd, u_quad_t start, u_quad_t len, uint_t *buf)
1654*7917SReza.Sabdar@Sun.COM {
1655*7917SReza.Sabdar@Sun.COM 	bm_io_t io;
1656*7917SReza.Sabdar@Sun.COM 	bm_iovec_t iov;
1657*7917SReza.Sabdar@Sun.COM 
1658*7917SReza.Sabdar@Sun.COM 	iov.bmv_base = start;
1659*7917SReza.Sabdar@Sun.COM 	iov.bmv_len = len;
1660*7917SReza.Sabdar@Sun.COM 	iov.bmv_val = buf;
1661*7917SReza.Sabdar@Sun.COM 	io.bmio_iovcnt = 1;
1662*7917SReza.Sabdar@Sun.COM 	io.bmio_iov = &iov;
1663*7917SReza.Sabdar@Sun.COM 
1664*7917SReza.Sabdar@Sun.COM 	return (dbm_getiov(bmd, &io));
1665*7917SReza.Sabdar@Sun.COM }
1666*7917SReza.Sabdar@Sun.COM 
1667*7917SReza.Sabdar@Sun.COM 
1668*7917SReza.Sabdar@Sun.COM /*
1669*7917SReza.Sabdar@Sun.COM  * dbm_getone
1670*7917SReza.Sabdar@Sun.COM  *
1671*7917SReza.Sabdar@Sun.COM  * Get only one bit.
1672*7917SReza.Sabdar@Sun.COM  */
1673*7917SReza.Sabdar@Sun.COM int
dbm_getone(int bmd,u_quad_t bitnum)1674*7917SReza.Sabdar@Sun.COM dbm_getone(int bmd, u_quad_t bitnum)
1675*7917SReza.Sabdar@Sun.COM {
1676*7917SReza.Sabdar@Sun.COM 	uint_t i;
1677*7917SReza.Sabdar@Sun.COM 
1678*7917SReza.Sabdar@Sun.COM 	if (dbm_get(bmd, bitnum, 1, &i) == 0)
1679*7917SReza.Sabdar@Sun.COM 		return (i ? 1 : 0);
1680*7917SReza.Sabdar@Sun.COM 
1681*7917SReza.Sabdar@Sun.COM 	return (0);
1682*7917SReza.Sabdar@Sun.COM }
1683