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