1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (C) 2012 Red Hat, Inc. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * This file is released under the GPL. 5*4882a593Smuzhiyun */ 6*4882a593Smuzhiyun #ifndef _LINUX_DM_BITSET_H 7*4882a593Smuzhiyun #define _LINUX_DM_BITSET_H 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #include "dm-array.h" 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun /*----------------------------------------------------------------*/ 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun /* 14*4882a593Smuzhiyun * This bitset type is a thin wrapper round a dm_array of 64bit words. It 15*4882a593Smuzhiyun * uses a tiny, one word cache to reduce the number of array lookups and so 16*4882a593Smuzhiyun * increase performance. 17*4882a593Smuzhiyun * 18*4882a593Smuzhiyun * Like the dm-array that it's based on, the caller needs to keep track of 19*4882a593Smuzhiyun * the size of the bitset separately. The underlying dm-array implicitly 20*4882a593Smuzhiyun * knows how many words it's storing and will return -ENODATA if you try 21*4882a593Smuzhiyun * and access an out of bounds word. However, an out of bounds bit in the 22*4882a593Smuzhiyun * final word will _not_ be detected, you have been warned. 23*4882a593Smuzhiyun * 24*4882a593Smuzhiyun * Bits are indexed from zero. 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun * Typical use: 27*4882a593Smuzhiyun * 28*4882a593Smuzhiyun * a) Initialise a dm_disk_bitset structure with dm_disk_bitset_init(). 29*4882a593Smuzhiyun * This describes the bitset and includes the cache. It's not called it 30*4882a593Smuzhiyun * dm_bitset_info in line with other data structures because it does 31*4882a593Smuzhiyun * include instance data. 32*4882a593Smuzhiyun * 33*4882a593Smuzhiyun * b) Get yourself a root. The root is the index of a block of data on the 34*4882a593Smuzhiyun * disk that holds a particular instance of an bitset. You may have a 35*4882a593Smuzhiyun * pre existing root in your metadata that you wish to use, or you may 36*4882a593Smuzhiyun * want to create a brand new, empty bitset with dm_bitset_empty(). 37*4882a593Smuzhiyun * 38*4882a593Smuzhiyun * Like the other data structures in this library, dm_bitset objects are 39*4882a593Smuzhiyun * immutable between transactions. Update functions will return you the 40*4882a593Smuzhiyun * root for a _new_ array. If you've incremented the old root, via 41*4882a593Smuzhiyun * dm_tm_inc(), before calling the update function you may continue to use 42*4882a593Smuzhiyun * it in parallel with the new root. 43*4882a593Smuzhiyun * 44*4882a593Smuzhiyun * Even read operations may trigger the cache to be flushed and as such 45*4882a593Smuzhiyun * return a root for a new, updated bitset. 46*4882a593Smuzhiyun * 47*4882a593Smuzhiyun * c) resize a bitset with dm_bitset_resize(). 48*4882a593Smuzhiyun * 49*4882a593Smuzhiyun * d) Set a bit with dm_bitset_set_bit(). 50*4882a593Smuzhiyun * 51*4882a593Smuzhiyun * e) Clear a bit with dm_bitset_clear_bit(). 52*4882a593Smuzhiyun * 53*4882a593Smuzhiyun * f) Test a bit with dm_bitset_test_bit(). 54*4882a593Smuzhiyun * 55*4882a593Smuzhiyun * g) Flush all updates from the cache with dm_bitset_flush(). 56*4882a593Smuzhiyun * 57*4882a593Smuzhiyun * h) Destroy the bitset with dm_bitset_del(). This tells the transaction 58*4882a593Smuzhiyun * manager that you're no longer using this data structure so it can 59*4882a593Smuzhiyun * recycle it's blocks. (dm_bitset_dec() would be a better name for it, 60*4882a593Smuzhiyun * but del is in keeping with dm_btree_del()). 61*4882a593Smuzhiyun */ 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun /* 64*4882a593Smuzhiyun * Opaque object. Unlike dm_array_info, you should have one of these per 65*4882a593Smuzhiyun * bitset. Initialise with dm_disk_bitset_init(). 66*4882a593Smuzhiyun */ 67*4882a593Smuzhiyun struct dm_disk_bitset { 68*4882a593Smuzhiyun struct dm_array_info array_info; 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun uint32_t current_index; 71*4882a593Smuzhiyun uint64_t current_bits; 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun bool current_index_set:1; 74*4882a593Smuzhiyun bool dirty:1; 75*4882a593Smuzhiyun }; 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun /* 78*4882a593Smuzhiyun * Sets up a dm_disk_bitset structure. You don't need to do anything with 79*4882a593Smuzhiyun * this structure when you finish using it. 80*4882a593Smuzhiyun * 81*4882a593Smuzhiyun * tm - the transaction manager that should supervise this structure 82*4882a593Smuzhiyun * info - the structure being initialised 83*4882a593Smuzhiyun */ 84*4882a593Smuzhiyun void dm_disk_bitset_init(struct dm_transaction_manager *tm, 85*4882a593Smuzhiyun struct dm_disk_bitset *info); 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* 88*4882a593Smuzhiyun * Create an empty, zero length bitset. 89*4882a593Smuzhiyun * 90*4882a593Smuzhiyun * info - describes the bitset 91*4882a593Smuzhiyun * new_root - on success, points to the new root block 92*4882a593Smuzhiyun */ 93*4882a593Smuzhiyun int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *new_root); 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun /* 96*4882a593Smuzhiyun * Creates a new bitset populated with values provided by a callback 97*4882a593Smuzhiyun * function. This is more efficient than creating an empty bitset, 98*4882a593Smuzhiyun * resizing, and then setting values since that process incurs a lot of 99*4882a593Smuzhiyun * copying. 100*4882a593Smuzhiyun * 101*4882a593Smuzhiyun * info - describes the array 102*4882a593Smuzhiyun * root - the root block of the array on disk 103*4882a593Smuzhiyun * size - the number of entries in the array 104*4882a593Smuzhiyun * fn - the callback 105*4882a593Smuzhiyun * context - passed to the callback 106*4882a593Smuzhiyun */ 107*4882a593Smuzhiyun typedef int (*bit_value_fn)(uint32_t index, bool *value, void *context); 108*4882a593Smuzhiyun int dm_bitset_new(struct dm_disk_bitset *info, dm_block_t *root, 109*4882a593Smuzhiyun uint32_t size, bit_value_fn fn, void *context); 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun /* 112*4882a593Smuzhiyun * Resize the bitset. 113*4882a593Smuzhiyun * 114*4882a593Smuzhiyun * info - describes the bitset 115*4882a593Smuzhiyun * old_root - the root block of the array on disk 116*4882a593Smuzhiyun * old_nr_entries - the number of bits in the old bitset 117*4882a593Smuzhiyun * new_nr_entries - the number of bits you want in the new bitset 118*4882a593Smuzhiyun * default_value - the value for any new bits 119*4882a593Smuzhiyun * new_root - on success, points to the new root block 120*4882a593Smuzhiyun */ 121*4882a593Smuzhiyun int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t old_root, 122*4882a593Smuzhiyun uint32_t old_nr_entries, uint32_t new_nr_entries, 123*4882a593Smuzhiyun bool default_value, dm_block_t *new_root); 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun /* 126*4882a593Smuzhiyun * Frees the bitset. 127*4882a593Smuzhiyun */ 128*4882a593Smuzhiyun int dm_bitset_del(struct dm_disk_bitset *info, dm_block_t root); 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun /* 131*4882a593Smuzhiyun * Set a bit. 132*4882a593Smuzhiyun * 133*4882a593Smuzhiyun * info - describes the bitset 134*4882a593Smuzhiyun * root - the root block of the bitset 135*4882a593Smuzhiyun * index - the bit index 136*4882a593Smuzhiyun * new_root - on success, points to the new root block 137*4882a593Smuzhiyun * 138*4882a593Smuzhiyun * -ENODATA will be returned if the index is out of bounds. 139*4882a593Smuzhiyun */ 140*4882a593Smuzhiyun int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root, 141*4882a593Smuzhiyun uint32_t index, dm_block_t *new_root); 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun /* 144*4882a593Smuzhiyun * Clears a bit. 145*4882a593Smuzhiyun * 146*4882a593Smuzhiyun * info - describes the bitset 147*4882a593Smuzhiyun * root - the root block of the bitset 148*4882a593Smuzhiyun * index - the bit index 149*4882a593Smuzhiyun * new_root - on success, points to the new root block 150*4882a593Smuzhiyun * 151*4882a593Smuzhiyun * -ENODATA will be returned if the index is out of bounds. 152*4882a593Smuzhiyun */ 153*4882a593Smuzhiyun int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root, 154*4882a593Smuzhiyun uint32_t index, dm_block_t *new_root); 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun /* 157*4882a593Smuzhiyun * Tests a bit. 158*4882a593Smuzhiyun * 159*4882a593Smuzhiyun * info - describes the bitset 160*4882a593Smuzhiyun * root - the root block of the bitset 161*4882a593Smuzhiyun * index - the bit index 162*4882a593Smuzhiyun * new_root - on success, points to the new root block (cached values may have been written) 163*4882a593Smuzhiyun * result - the bit value you're after 164*4882a593Smuzhiyun * 165*4882a593Smuzhiyun * -ENODATA will be returned if the index is out of bounds. 166*4882a593Smuzhiyun */ 167*4882a593Smuzhiyun int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root, 168*4882a593Smuzhiyun uint32_t index, dm_block_t *new_root, bool *result); 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun /* 171*4882a593Smuzhiyun * Flush any cached changes to disk. 172*4882a593Smuzhiyun * 173*4882a593Smuzhiyun * info - describes the bitset 174*4882a593Smuzhiyun * root - the root block of the bitset 175*4882a593Smuzhiyun * new_root - on success, points to the new root block 176*4882a593Smuzhiyun */ 177*4882a593Smuzhiyun int dm_bitset_flush(struct dm_disk_bitset *info, dm_block_t root, 178*4882a593Smuzhiyun dm_block_t *new_root); 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun struct dm_bitset_cursor { 181*4882a593Smuzhiyun struct dm_disk_bitset *info; 182*4882a593Smuzhiyun struct dm_array_cursor cursor; 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun uint32_t entries_remaining; 185*4882a593Smuzhiyun uint32_t array_index; 186*4882a593Smuzhiyun uint32_t bit_index; 187*4882a593Smuzhiyun uint64_t current_bits; 188*4882a593Smuzhiyun }; 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun /* 191*4882a593Smuzhiyun * Make sure you've flush any dm_disk_bitset and updated the root before 192*4882a593Smuzhiyun * using this. 193*4882a593Smuzhiyun */ 194*4882a593Smuzhiyun int dm_bitset_cursor_begin(struct dm_disk_bitset *info, 195*4882a593Smuzhiyun dm_block_t root, uint32_t nr_entries, 196*4882a593Smuzhiyun struct dm_bitset_cursor *c); 197*4882a593Smuzhiyun void dm_bitset_cursor_end(struct dm_bitset_cursor *c); 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun int dm_bitset_cursor_next(struct dm_bitset_cursor *c); 200*4882a593Smuzhiyun int dm_bitset_cursor_skip(struct dm_bitset_cursor *c, uint32_t count); 201*4882a593Smuzhiyun bool dm_bitset_cursor_get_value(struct dm_bitset_cursor *c); 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun /*----------------------------------------------------------------*/ 204*4882a593Smuzhiyun 205*4882a593Smuzhiyun #endif /* _LINUX_DM_BITSET_H */ 206