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
)
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;
82 EXPORT_SYMBOL_GPL(dm_bitset_flush
);
84 static int read_bits(struct dm_disk_bitset
*info
, dm_block_t root
,
90 r
= dm_array_get_value(&info
->array_info
, root
, array_index
, &value
);
94 info
->current_bits
= le64_to_cpu(value
);
95 info
->current_index_set
= true;
96 info
->current_index
= array_index
;
100 static int get_array_entry(struct dm_disk_bitset
*info
, dm_block_t root
,
101 uint32_t index
, dm_block_t
*new_root
)
104 unsigned array_index
= index
/ BITS_PER_ARRAY_ENTRY
;
106 if (info
->current_index_set
) {
107 if (info
->current_index
== array_index
)
110 r
= dm_bitset_flush(info
, root
, new_root
);
115 return read_bits(info
, root
, array_index
);
118 int dm_bitset_set_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
119 uint32_t index
, dm_block_t
*new_root
)
122 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
124 r
= get_array_entry(info
, root
, index
, new_root
);
128 set_bit(b
, (unsigned long *) &info
->current_bits
);
131 EXPORT_SYMBOL_GPL(dm_bitset_set_bit
);
133 int dm_bitset_clear_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
134 uint32_t index
, dm_block_t
*new_root
)
137 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
139 r
= get_array_entry(info
, root
, index
, new_root
);
143 clear_bit(b
, (unsigned long *) &info
->current_bits
);
146 EXPORT_SYMBOL_GPL(dm_bitset_clear_bit
);
148 int dm_bitset_test_bit(struct dm_disk_bitset
*info
, dm_block_t root
,
149 uint32_t index
, dm_block_t
*new_root
, bool *result
)
152 unsigned b
= index
% BITS_PER_ARRAY_ENTRY
;
154 r
= get_array_entry(info
, root
, index
, new_root
);
158 *result
= test_bit(b
, (unsigned long *) &info
->current_bits
);
161 EXPORT_SYMBOL_GPL(dm_bitset_test_bit
);
163 /*----------------------------------------------------------------*/