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 int dm_bitset_resize(struct dm_disk_bitset
*info
, dm_block_t root
,
43 uint32_t old_nr_entries
, uint32_t new_nr_entries
,
44 bool default_value
, dm_block_t
*new_root
)
46 uint32_t old_blocks
= dm_div_up(old_nr_entries
, BITS_PER_ARRAY_ENTRY
);
47 uint32_t new_blocks
= dm_div_up(new_nr_entries
, BITS_PER_ARRAY_ENTRY
);
48 __le64 value
= default_value
? cpu_to_le64(~0) : cpu_to_le64(0);
50 __dm_bless_for_disk(&value
);
51 return dm_array_resize(&info
->array_info
, root
, old_blocks
, new_blocks
,
54 EXPORT_SYMBOL_GPL(dm_bitset_resize
);
56 int dm_bitset_del(struct dm_disk_bitset
*info
, dm_block_t root
)
58 return dm_array_del(&info
->array_info
, root
);
60 EXPORT_SYMBOL_GPL(dm_bitset_del
);
62 int dm_bitset_flush(struct dm_disk_bitset
*info
, dm_block_t root
,
68 if (!info
->current_index_set
|| !info
->dirty
)
71 value
= cpu_to_le64(info
->current_bits
);
73 __dm_bless_for_disk(&value
);
74 r
= dm_array_set_value(&info
->array_info
, root
, info
->current_index
,
79 info
->current_index_set
= false;
84 EXPORT_SYMBOL_GPL(dm_bitset_flush
);
86 static int read_bits(struct dm_disk_bitset
*info
, dm_block_t root
,
92 r
= dm_array_get_value(&info
->array_info
, root
, array_index
, &value
);
96 info
->current_bits
= le64_to_cpu(value
);
97 info
->current_index_set
= true;
98 info
->current_index
= array_index
;
104 static int get_array_entry(struct dm_disk_bitset
*info
, dm_block_t root
,
105 uint32_t index
, dm_block_t
*new_root
)
108 unsigned array_index
= index
/ BITS_PER_ARRAY_ENTRY
;
110 if (info
->current_index_set
) {
111 if (info
->current_index
== array_index
)
114 r
= dm_bitset_flush(info
, root
, new_root
);
119 return read_bits(info
, root
, array_index
);
122 int dm_bitset_set_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
123 uint32_t index
, dm_block_t
*new_root
)
126 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
128 r
= get_array_entry(info
, root
, index
, new_root
);
132 set_bit(b
, (unsigned long *) &info
->current_bits
);
137 EXPORT_SYMBOL_GPL(dm_bitset_set_bit
);
139 int dm_bitset_clear_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
140 uint32_t index
, dm_block_t
*new_root
)
143 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
145 r
= get_array_entry(info
, root
, index
, new_root
);
149 clear_bit(b
, (unsigned long *) &info
->current_bits
);
154 EXPORT_SYMBOL_GPL(dm_bitset_clear_bit
);
156 int dm_bitset_test_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
157 uint32_t index
, dm_block_t
*new_root
, bool *result
)
160 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
162 r
= get_array_entry(info
, root
, index
, new_root
);
166 *result
= test_bit(b
, (unsigned long *) &info
->current_bits
);
169 EXPORT_SYMBOL_GPL(dm_bitset_test_bit
);
171 /*----------------------------------------------------------------*/