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 * 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 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 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 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 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 * 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 * 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 * 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 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 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 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 * 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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