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