xref: /openbmc/linux/drivers/md/persistent-data/dm-bitset.c (revision 7a87edfee75151abb69d47dba2277ff2de0f6071)
1*7a87edfeSJoe Thornber /*
2*7a87edfeSJoe Thornber  * Copyright (C) 2012 Red Hat, Inc.
3*7a87edfeSJoe Thornber  *
4*7a87edfeSJoe Thornber  * This file is released under the GPL.
5*7a87edfeSJoe Thornber  */
6*7a87edfeSJoe Thornber 
7*7a87edfeSJoe Thornber #include "dm-bitset.h"
8*7a87edfeSJoe Thornber #include "dm-transaction-manager.h"
9*7a87edfeSJoe Thornber 
10*7a87edfeSJoe Thornber #include <linux/export.h>
11*7a87edfeSJoe Thornber #include <linux/device-mapper.h>
12*7a87edfeSJoe Thornber 
13*7a87edfeSJoe Thornber #define DM_MSG_PREFIX "bitset"
14*7a87edfeSJoe Thornber #define BITS_PER_ARRAY_ENTRY 64
15*7a87edfeSJoe Thornber 
16*7a87edfeSJoe Thornber /*----------------------------------------------------------------*/
17*7a87edfeSJoe Thornber 
18*7a87edfeSJoe Thornber static struct dm_btree_value_type bitset_bvt = {
19*7a87edfeSJoe Thornber 	.context = NULL,
20*7a87edfeSJoe Thornber 	.size = sizeof(__le64),
21*7a87edfeSJoe Thornber 	.inc = NULL,
22*7a87edfeSJoe Thornber 	.dec = NULL,
23*7a87edfeSJoe Thornber 	.equal = NULL,
24*7a87edfeSJoe Thornber };
25*7a87edfeSJoe Thornber 
26*7a87edfeSJoe Thornber /*----------------------------------------------------------------*/
27*7a87edfeSJoe Thornber 
28*7a87edfeSJoe Thornber void dm_disk_bitset_init(struct dm_transaction_manager *tm,
29*7a87edfeSJoe Thornber 			 struct dm_disk_bitset *info)
30*7a87edfeSJoe Thornber {
31*7a87edfeSJoe Thornber 	dm_array_info_init(&info->array_info, tm, &bitset_bvt);
32*7a87edfeSJoe Thornber 	info->current_index_set = false;
33*7a87edfeSJoe Thornber }
34*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_disk_bitset_init);
35*7a87edfeSJoe Thornber 
36*7a87edfeSJoe Thornber int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *root)
37*7a87edfeSJoe Thornber {
38*7a87edfeSJoe Thornber 	return dm_array_empty(&info->array_info, root);
39*7a87edfeSJoe Thornber }
40*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_empty);
41*7a87edfeSJoe Thornber 
42*7a87edfeSJoe Thornber int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t root,
43*7a87edfeSJoe Thornber 		     uint32_t old_nr_entries, uint32_t new_nr_entries,
44*7a87edfeSJoe Thornber 		     bool default_value, dm_block_t *new_root)
45*7a87edfeSJoe Thornber {
46*7a87edfeSJoe Thornber 	uint32_t old_blocks = dm_div_up(old_nr_entries, BITS_PER_ARRAY_ENTRY);
47*7a87edfeSJoe Thornber 	uint32_t new_blocks = dm_div_up(new_nr_entries, BITS_PER_ARRAY_ENTRY);
48*7a87edfeSJoe Thornber 	__le64 value = default_value ? cpu_to_le64(~0) : cpu_to_le64(0);
49*7a87edfeSJoe Thornber 
50*7a87edfeSJoe Thornber 	__dm_bless_for_disk(&value);
51*7a87edfeSJoe Thornber 	return dm_array_resize(&info->array_info, root, old_blocks, new_blocks,
52*7a87edfeSJoe Thornber 			       &value, new_root);
53*7a87edfeSJoe Thornber }
54*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_resize);
55*7a87edfeSJoe Thornber 
56*7a87edfeSJoe Thornber int dm_bitset_del(struct dm_disk_bitset *info, dm_block_t root)
57*7a87edfeSJoe Thornber {
58*7a87edfeSJoe Thornber 	return dm_array_del(&info->array_info, root);
59*7a87edfeSJoe Thornber }
60*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_del);
61*7a87edfeSJoe Thornber 
62*7a87edfeSJoe Thornber int dm_bitset_flush(struct dm_disk_bitset *info, dm_block_t root,
63*7a87edfeSJoe Thornber 		    dm_block_t *new_root)
64*7a87edfeSJoe Thornber {
65*7a87edfeSJoe Thornber 	int r;
66*7a87edfeSJoe Thornber 	__le64 value;
67*7a87edfeSJoe Thornber 
68*7a87edfeSJoe Thornber 	if (!info->current_index_set)
69*7a87edfeSJoe Thornber 		return 0;
70*7a87edfeSJoe Thornber 
71*7a87edfeSJoe Thornber 	value = cpu_to_le64(info->current_bits);
72*7a87edfeSJoe Thornber 
73*7a87edfeSJoe Thornber 	__dm_bless_for_disk(&value);
74*7a87edfeSJoe Thornber 	r = dm_array_set_value(&info->array_info, root, info->current_index,
75*7a87edfeSJoe Thornber 			       &value, new_root);
76*7a87edfeSJoe Thornber 	if (r)
77*7a87edfeSJoe Thornber 		return r;
78*7a87edfeSJoe Thornber 
79*7a87edfeSJoe Thornber 	info->current_index_set = false;
80*7a87edfeSJoe Thornber 	return 0;
81*7a87edfeSJoe Thornber }
82*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_flush);
83*7a87edfeSJoe Thornber 
84*7a87edfeSJoe Thornber static int read_bits(struct dm_disk_bitset *info, dm_block_t root,
85*7a87edfeSJoe Thornber 		     uint32_t array_index)
86*7a87edfeSJoe Thornber {
87*7a87edfeSJoe Thornber 	int r;
88*7a87edfeSJoe Thornber 	__le64 value;
89*7a87edfeSJoe Thornber 
90*7a87edfeSJoe Thornber 	r = dm_array_get_value(&info->array_info, root, array_index, &value);
91*7a87edfeSJoe Thornber 	if (r)
92*7a87edfeSJoe Thornber 		return r;
93*7a87edfeSJoe Thornber 
94*7a87edfeSJoe Thornber 	info->current_bits = le64_to_cpu(value);
95*7a87edfeSJoe Thornber 	info->current_index_set = true;
96*7a87edfeSJoe Thornber 	info->current_index = array_index;
97*7a87edfeSJoe Thornber 	return 0;
98*7a87edfeSJoe Thornber }
99*7a87edfeSJoe Thornber 
100*7a87edfeSJoe Thornber static int get_array_entry(struct dm_disk_bitset *info, dm_block_t root,
101*7a87edfeSJoe Thornber 			   uint32_t index, dm_block_t *new_root)
102*7a87edfeSJoe Thornber {
103*7a87edfeSJoe Thornber 	int r;
104*7a87edfeSJoe Thornber 	unsigned array_index = index / BITS_PER_ARRAY_ENTRY;
105*7a87edfeSJoe Thornber 
106*7a87edfeSJoe Thornber 	if (info->current_index_set) {
107*7a87edfeSJoe Thornber 		if (info->current_index == array_index)
108*7a87edfeSJoe Thornber 			return 0;
109*7a87edfeSJoe Thornber 
110*7a87edfeSJoe Thornber 		r = dm_bitset_flush(info, root, new_root);
111*7a87edfeSJoe Thornber 		if (r)
112*7a87edfeSJoe Thornber 			return r;
113*7a87edfeSJoe Thornber 	}
114*7a87edfeSJoe Thornber 
115*7a87edfeSJoe Thornber 	return read_bits(info, root, array_index);
116*7a87edfeSJoe Thornber }
117*7a87edfeSJoe Thornber 
118*7a87edfeSJoe Thornber int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root,
119*7a87edfeSJoe Thornber 		      uint32_t index, dm_block_t *new_root)
120*7a87edfeSJoe Thornber {
121*7a87edfeSJoe Thornber 	int r;
122*7a87edfeSJoe Thornber 	unsigned b = index % BITS_PER_ARRAY_ENTRY;
123*7a87edfeSJoe Thornber 
124*7a87edfeSJoe Thornber 	r = get_array_entry(info, root, index, new_root);
125*7a87edfeSJoe Thornber 	if (r)
126*7a87edfeSJoe Thornber 		return r;
127*7a87edfeSJoe Thornber 
128*7a87edfeSJoe Thornber 	set_bit(b, (unsigned long *) &info->current_bits);
129*7a87edfeSJoe Thornber 	return 0;
130*7a87edfeSJoe Thornber }
131*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_set_bit);
132*7a87edfeSJoe Thornber 
133*7a87edfeSJoe Thornber int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root,
134*7a87edfeSJoe Thornber 			uint32_t index, dm_block_t *new_root)
135*7a87edfeSJoe Thornber {
136*7a87edfeSJoe Thornber 	int r;
137*7a87edfeSJoe Thornber 	unsigned b = index % BITS_PER_ARRAY_ENTRY;
138*7a87edfeSJoe Thornber 
139*7a87edfeSJoe Thornber 	r = get_array_entry(info, root, index, new_root);
140*7a87edfeSJoe Thornber 	if (r)
141*7a87edfeSJoe Thornber 		return r;
142*7a87edfeSJoe Thornber 
143*7a87edfeSJoe Thornber 	clear_bit(b, (unsigned long *) &info->current_bits);
144*7a87edfeSJoe Thornber 	return 0;
145*7a87edfeSJoe Thornber }
146*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_clear_bit);
147*7a87edfeSJoe Thornber 
148*7a87edfeSJoe Thornber int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root,
149*7a87edfeSJoe Thornber 		       uint32_t index, dm_block_t *new_root, bool *result)
150*7a87edfeSJoe Thornber {
151*7a87edfeSJoe Thornber 	int r;
152*7a87edfeSJoe Thornber 	unsigned b = index % BITS_PER_ARRAY_ENTRY;
153*7a87edfeSJoe Thornber 
154*7a87edfeSJoe Thornber 	r = get_array_entry(info, root, index, new_root);
155*7a87edfeSJoe Thornber 	if (r)
156*7a87edfeSJoe Thornber 		return r;
157*7a87edfeSJoe Thornber 
158*7a87edfeSJoe Thornber 	*result = test_bit(b, (unsigned long *) &info->current_bits);
159*7a87edfeSJoe Thornber 	return 0;
160*7a87edfeSJoe Thornber }
161*7a87edfeSJoe Thornber EXPORT_SYMBOL_GPL(dm_bitset_test_bit);
162*7a87edfeSJoe Thornber 
163*7a87edfeSJoe Thornber /*----------------------------------------------------------------*/
164