![]() |
|
|||
0001 /* 0002 * Copyright (C) 2012 Red Hat, Inc. 0003 * 0004 * This file is released under the GPL. 0005 */ 0006 #ifndef _LINUX_DM_BITSET_H 0007 #define _LINUX_DM_BITSET_H 0008 0009 #include "dm-array.h" 0010 0011 /*----------------------------------------------------------------*/ 0012 0013 /* 0014 * This bitset type is a thin wrapper round a dm_array of 64bit words. It 0015 * uses a tiny, one word cache to reduce the number of array lookups and so 0016 * increase performance. 0017 * 0018 * Like the dm-array that it's based on, the caller needs to keep track of 0019 * the size of the bitset separately. The underlying dm-array implicitly 0020 * knows how many words it's storing and will return -ENODATA if you try 0021 * and access an out of bounds word. However, an out of bounds bit in the 0022 * final word will _not_ be detected, you have been warned. 0023 * 0024 * Bits are indexed from zero. 0025 0026 * Typical use: 0027 * 0028 * a) Initialise a dm_disk_bitset structure with dm_disk_bitset_init(). 0029 * This describes the bitset and includes the cache. It's not called it 0030 * dm_bitset_info in line with other data structures because it does 0031 * include instance data. 0032 * 0033 * b) Get yourself a root. The root is the index of a block of data on the 0034 * disk that holds a particular instance of an bitset. You may have a 0035 * pre existing root in your metadata that you wish to use, or you may 0036 * want to create a brand new, empty bitset with dm_bitset_empty(). 0037 * 0038 * Like the other data structures in this library, dm_bitset objects are 0039 * immutable between transactions. Update functions will return you the 0040 * root for a _new_ array. If you've incremented the old root, via 0041 * dm_tm_inc(), before calling the update function you may continue to use 0042 * it in parallel with the new root. 0043 * 0044 * Even read operations may trigger the cache to be flushed and as such 0045 * return a root for a new, updated bitset. 0046 * 0047 * c) resize a bitset with dm_bitset_resize(). 0048 * 0049 * d) Set a bit with dm_bitset_set_bit(). 0050 * 0051 * e) Clear a bit with dm_bitset_clear_bit(). 0052 * 0053 * f) Test a bit with dm_bitset_test_bit(). 0054 * 0055 * g) Flush all updates from the cache with dm_bitset_flush(). 0056 * 0057 * h) Destroy the bitset with dm_bitset_del(). This tells the transaction 0058 * manager that you're no longer using this data structure so it can 0059 * recycle it's blocks. (dm_bitset_dec() would be a better name for it, 0060 * but del is in keeping with dm_btree_del()). 0061 */ 0062 0063 /* 0064 * Opaque object. Unlike dm_array_info, you should have one of these per 0065 * bitset. Initialise with dm_disk_bitset_init(). 0066 */ 0067 struct dm_disk_bitset { 0068 struct dm_array_info array_info; 0069 0070 uint32_t current_index; 0071 uint64_t current_bits; 0072 0073 bool current_index_set:1; 0074 bool dirty:1; 0075 }; 0076 0077 /* 0078 * Sets up a dm_disk_bitset structure. You don't need to do anything with 0079 * this structure when you finish using it. 0080 * 0081 * tm - the transaction manager that should supervise this structure 0082 * info - the structure being initialised 0083 */ 0084 void dm_disk_bitset_init(struct dm_transaction_manager *tm, 0085 struct dm_disk_bitset *info); 0086 0087 /* 0088 * Create an empty, zero length bitset. 0089 * 0090 * info - describes the bitset 0091 * new_root - on success, points to the new root block 0092 */ 0093 int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *new_root); 0094 0095 /* 0096 * Creates a new bitset populated with values provided by a callback 0097 * function. This is more efficient than creating an empty bitset, 0098 * resizing, and then setting values since that process incurs a lot of 0099 * copying. 0100 * 0101 * info - describes the array 0102 * root - the root block of the array on disk 0103 * size - the number of entries in the array 0104 * fn - the callback 0105 * context - passed to the callback 0106 */ 0107 typedef int (*bit_value_fn)(uint32_t index, bool *value, void *context); 0108 int dm_bitset_new(struct dm_disk_bitset *info, dm_block_t *root, 0109 uint32_t size, bit_value_fn fn, void *context); 0110 0111 /* 0112 * Resize the bitset. 0113 * 0114 * info - describes the bitset 0115 * old_root - the root block of the array on disk 0116 * old_nr_entries - the number of bits in the old bitset 0117 * new_nr_entries - the number of bits you want in the new bitset 0118 * default_value - the value for any new bits 0119 * new_root - on success, points to the new root block 0120 */ 0121 int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t old_root, 0122 uint32_t old_nr_entries, uint32_t new_nr_entries, 0123 bool default_value, dm_block_t *new_root); 0124 0125 /* 0126 * Frees the bitset. 0127 */ 0128 int dm_bitset_del(struct dm_disk_bitset *info, dm_block_t root); 0129 0130 /* 0131 * Set a bit. 0132 * 0133 * info - describes the bitset 0134 * root - the root block of the bitset 0135 * index - the bit index 0136 * new_root - on success, points to the new root block 0137 * 0138 * -ENODATA will be returned if the index is out of bounds. 0139 */ 0140 int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root, 0141 uint32_t index, dm_block_t *new_root); 0142 0143 /* 0144 * Clears a bit. 0145 * 0146 * info - describes the bitset 0147 * root - the root block of the bitset 0148 * index - the bit index 0149 * new_root - on success, points to the new root block 0150 * 0151 * -ENODATA will be returned if the index is out of bounds. 0152 */ 0153 int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root, 0154 uint32_t index, dm_block_t *new_root); 0155 0156 /* 0157 * Tests a bit. 0158 * 0159 * info - describes the bitset 0160 * root - the root block of the bitset 0161 * index - the bit index 0162 * new_root - on success, points to the new root block (cached values may have been written) 0163 * result - the bit value you're after 0164 * 0165 * -ENODATA will be returned if the index is out of bounds. 0166 */ 0167 int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root, 0168 uint32_t index, dm_block_t *new_root, bool *result); 0169 0170 /* 0171 * Flush any cached changes to disk. 0172 * 0173 * info - describes the bitset 0174 * root - the root block of the bitset 0175 * new_root - on success, points to the new root block 0176 */ 0177 int dm_bitset_flush(struct dm_disk_bitset *info, dm_block_t root, 0178 dm_block_t *new_root); 0179 0180 struct dm_bitset_cursor { 0181 struct dm_disk_bitset *info; 0182 struct dm_array_cursor cursor; 0183 0184 uint32_t entries_remaining; 0185 uint32_t array_index; 0186 uint32_t bit_index; 0187 uint64_t current_bits; 0188 }; 0189 0190 /* 0191 * Make sure you've flush any dm_disk_bitset and updated the root before 0192 * using this. 0193 */ 0194 int dm_bitset_cursor_begin(struct dm_disk_bitset *info, 0195 dm_block_t root, uint32_t nr_entries, 0196 struct dm_bitset_cursor *c); 0197 void dm_bitset_cursor_end(struct dm_bitset_cursor *c); 0198 0199 int dm_bitset_cursor_next(struct dm_bitset_cursor *c); 0200 int dm_bitset_cursor_skip(struct dm_bitset_cursor *c, uint32_t count); 0201 bool dm_bitset_cursor_get_value(struct dm_bitset_cursor *c); 0202 0203 /*----------------------------------------------------------------*/ 0204 0205 #endif /* _LINUX_DM_BITSET_H */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |