2 * Copyright (C) 2012 Red Hat, Inc.
4 * This file is released under the GPL.
8 #include "dm-transaction-manager.h"
10 #include <linux/export.h>
11 #include <linux/device-mapper.h>
13 #define DM_MSG_PREFIX "bitset"
14 #define BITS_PER_ARRAY_ENTRY 64
16 /*----------------------------------------------------------------*/
18 static struct dm_btree_value_type bitset_bvt
= {
20 .size
= sizeof(__le64
),
26 /*----------------------------------------------------------------*/
28 void dm_disk_bitset_init(struct dm_transaction_manager
*tm
,
29 struct dm_disk_bitset
*info
)
31 dm_array_info_init(&info
->array_info
, tm
, &bitset_bvt
);
32 info
->current_index_set
= false;
34 EXPORT_SYMBOL_GPL(dm_disk_bitset_init
);
36 int dm_bitset_empty(struct dm_disk_bitset
*info
, dm_block_t
*root
)
38 return dm_array_empty(&info
->array_info
, root
);
40 EXPORT_SYMBOL_GPL(dm_bitset_empty
);
42 struct packer_context
{
48 static int pack_bits(uint32_t index
, void *value
, void *context
)
51 struct packer_context
*p
= context
;
52 unsigned bit
, nr
= min(64u, p
->nr_bits
- (index
* 64));
56 for (bit
= 0; bit
< nr
; bit
++) {
57 r
= p
->fn(index
* 64 + bit
, &bv
, p
->context
);
62 set_bit(bit
, (unsigned long *) &word
);
64 clear_bit(bit
, (unsigned long *) &word
);
67 *((__le64
*) value
) = cpu_to_le64(word
);
72 int dm_bitset_new(struct dm_disk_bitset
*info
, dm_block_t
*root
,
73 uint32_t size
, bit_value_fn fn
, void *context
)
75 struct packer_context p
;
80 return dm_array_new(&info
->array_info
, root
, dm_div_up(size
, 64), pack_bits
, &p
);
82 EXPORT_SYMBOL_GPL(dm_bitset_new
);
84 int dm_bitset_resize(struct dm_disk_bitset
*info
, dm_block_t root
,
85 uint32_t old_nr_entries
, uint32_t new_nr_entries
,
86 bool default_value
, dm_block_t
*new_root
)
88 uint32_t old_blocks
= dm_div_up(old_nr_entries
, BITS_PER_ARRAY_ENTRY
);
89 uint32_t new_blocks
= dm_div_up(new_nr_entries
, BITS_PER_ARRAY_ENTRY
);
90 __le64 value
= default_value
? cpu_to_le64(~0) : cpu_to_le64(0);
92 __dm_bless_for_disk(&value
);
93 return dm_array_resize(&info
->array_info
, root
, old_blocks
, new_blocks
,
96 EXPORT_SYMBOL_GPL(dm_bitset_resize
);
98 int dm_bitset_del(struct dm_disk_bitset
*info
, dm_block_t root
)
100 return dm_array_del(&info
->array_info
, root
);
102 EXPORT_SYMBOL_GPL(dm_bitset_del
);
104 int dm_bitset_flush(struct dm_disk_bitset
*info
, dm_block_t root
,
105 dm_block_t
*new_root
)
110 if (!info
->current_index_set
|| !info
->dirty
)
113 value
= cpu_to_le64(info
->current_bits
);
115 __dm_bless_for_disk(&value
);
116 r
= dm_array_set_value(&info
->array_info
, root
, info
->current_index
,
121 info
->current_index_set
= false;
126 EXPORT_SYMBOL_GPL(dm_bitset_flush
);
128 static int read_bits(struct dm_disk_bitset
*info
, dm_block_t root
,
129 uint32_t array_index
)
134 r
= dm_array_get_value(&info
->array_info
, root
, array_index
, &value
);
138 info
->current_bits
= le64_to_cpu(value
);
139 info
->current_index_set
= true;
140 info
->current_index
= array_index
;
146 static int get_array_entry(struct dm_disk_bitset
*info
, dm_block_t root
,
147 uint32_t index
, dm_block_t
*new_root
)
150 unsigned array_index
= index
/ BITS_PER_ARRAY_ENTRY
;
152 if (info
->current_index_set
) {
153 if (info
->current_index
== array_index
)
156 r
= dm_bitset_flush(info
, root
, new_root
);
161 return read_bits(info
, root
, array_index
);
164 int dm_bitset_set_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
165 uint32_t index
, dm_block_t
*new_root
)
168 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
170 r
= get_array_entry(info
, root
, index
, new_root
);
174 set_bit(b
, (unsigned long *) &info
->current_bits
);
179 EXPORT_SYMBOL_GPL(dm_bitset_set_bit
);
181 int dm_bitset_clear_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
182 uint32_t index
, dm_block_t
*new_root
)
185 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
187 r
= get_array_entry(info
, root
, index
, new_root
);
191 clear_bit(b
, (unsigned long *) &info
->current_bits
);
196 EXPORT_SYMBOL_GPL(dm_bitset_clear_bit
);
198 int dm_bitset_test_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
199 uint32_t index
, dm_block_t
*new_root
, bool *result
)
202 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
204 r
= get_array_entry(info
, root
, index
, new_root
);
208 *result
= test_bit(b
, (unsigned long *) &info
->current_bits
);
211 EXPORT_SYMBOL_GPL(dm_bitset_test_bit
);
213 static int cursor_next_array_entry(struct dm_bitset_cursor
*c
)
218 r
= dm_array_cursor_next(&c
->cursor
);
222 dm_array_cursor_get_value(&c
->cursor
, (void **) &value
);
225 c
->current_bits
= le64_to_cpu(*value
);
229 int dm_bitset_cursor_begin(struct dm_disk_bitset
*info
,
230 dm_block_t root
, uint32_t nr_entries
,
231 struct dm_bitset_cursor
*c
)
240 c
->entries_remaining
= nr_entries
;
242 r
= dm_array_cursor_begin(&info
->array_info
, root
, &c
->cursor
);
246 dm_array_cursor_get_value(&c
->cursor
, (void **) &value
);
249 c
->current_bits
= le64_to_cpu(*value
);
253 EXPORT_SYMBOL_GPL(dm_bitset_cursor_begin
);
255 void dm_bitset_cursor_end(struct dm_bitset_cursor
*c
)
257 return dm_array_cursor_end(&c
->cursor
);
259 EXPORT_SYMBOL_GPL(dm_bitset_cursor_end
);
261 int dm_bitset_cursor_next(struct dm_bitset_cursor
*c
)
265 if (!c
->entries_remaining
)
268 c
->entries_remaining
--;
269 if (++c
->bit_index
> 63)
270 r
= cursor_next_array_entry(c
);
274 EXPORT_SYMBOL_GPL(dm_bitset_cursor_next
);
276 int dm_bitset_cursor_skip(struct dm_bitset_cursor
*c
, uint32_t count
)
280 uint32_t nr_array_skip
;
281 uint32_t remaining_in_word
= 64 - c
->bit_index
;
283 if (c
->entries_remaining
< count
)
286 if (count
< remaining_in_word
) {
287 c
->bit_index
+= count
;
288 c
->entries_remaining
-= count
;
292 c
->entries_remaining
-= remaining_in_word
;
293 count
-= remaining_in_word
;
296 nr_array_skip
= (count
/ 64) + 1;
297 r
= dm_array_cursor_skip(&c
->cursor
, nr_array_skip
);
301 dm_array_cursor_get_value(&c
->cursor
, (void **) &value
);
302 c
->entries_remaining
-= count
;
303 c
->array_index
+= nr_array_skip
;
304 c
->bit_index
= count
& 63;
305 c
->current_bits
= le64_to_cpu(*value
);
309 EXPORT_SYMBOL_GPL(dm_bitset_cursor_skip
);
311 bool dm_bitset_cursor_get_value(struct dm_bitset_cursor
*c
)
313 return test_bit(c
->bit_index
, (unsigned long *) &c
->current_bits
);
315 EXPORT_SYMBOL_GPL(dm_bitset_cursor_get_value
);
317 /*----------------------------------------------------------------*/