diff options
-rw-r--r-- | drivers/md/persistent-data/dm-bitset.c | 42 | ||||
-rw-r--r-- | drivers/md/persistent-data/dm-bitset.h | 16 |
2 files changed, 58 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-bitset.c b/drivers/md/persistent-data/dm-bitset.c index 7cb28516cc19..fbf8d9bc4d15 100644 --- a/drivers/md/persistent-data/dm-bitset.c +++ b/drivers/md/persistent-data/dm-bitset.c | |||
@@ -39,6 +39,48 @@ int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *root) | |||
39 | } | 39 | } |
40 | EXPORT_SYMBOL_GPL(dm_bitset_empty); | 40 | EXPORT_SYMBOL_GPL(dm_bitset_empty); |
41 | 41 | ||
42 | struct packer_context { | ||
43 | bit_value_fn fn; | ||
44 | unsigned nr_bits; | ||
45 | void *context; | ||
46 | }; | ||
47 | |||
48 | static int pack_bits(uint32_t index, void *value, void *context) | ||
49 | { | ||
50 | int r; | ||
51 | struct packer_context *p = context; | ||
52 | unsigned bit, nr = min(64u, p->nr_bits - (index * 64)); | ||
53 | uint64_t word = 0; | ||
54 | bool bv; | ||
55 | |||
56 | for (bit = 0; bit < nr; bit++) { | ||
57 | r = p->fn(index * 64 + bit, &bv, p->context); | ||
58 | if (r) | ||
59 | return r; | ||
60 | |||
61 | if (bv) | ||
62 | set_bit(bit, (unsigned long *) &word); | ||
63 | else | ||
64 | clear_bit(bit, (unsigned long *) &word); | ||
65 | } | ||
66 | |||
67 | *((__le64 *) value) = cpu_to_le64(word); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | int dm_bitset_new(struct dm_disk_bitset *info, dm_block_t *root, | ||
73 | uint32_t size, bit_value_fn fn, void *context) | ||
74 | { | ||
75 | struct packer_context p; | ||
76 | p.fn = fn; | ||
77 | p.nr_bits = size; | ||
78 | p.context = context; | ||
79 | |||
80 | return dm_array_new(&info->array_info, root, dm_div_up(size, 64), pack_bits, &p); | ||
81 | } | ||
82 | EXPORT_SYMBOL_GPL(dm_bitset_new); | ||
83 | |||
42 | int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t root, | 84 | int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t root, |
43 | uint32_t old_nr_entries, uint32_t new_nr_entries, | 85 | uint32_t old_nr_entries, uint32_t new_nr_entries, |
44 | bool default_value, dm_block_t *new_root) | 86 | bool default_value, dm_block_t *new_root) |
diff --git a/drivers/md/persistent-data/dm-bitset.h b/drivers/md/persistent-data/dm-bitset.h index 017c0d42cdbf..a08636898a43 100644 --- a/drivers/md/persistent-data/dm-bitset.h +++ b/drivers/md/persistent-data/dm-bitset.h | |||
@@ -93,6 +93,22 @@ void dm_disk_bitset_init(struct dm_transaction_manager *tm, | |||
93 | int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *new_root); | 93 | int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *new_root); |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * Creates a new bitset populated with values provided by a callback | ||
97 | * function. This is more efficient than creating an empty bitset, | ||
98 | * resizing, and then setting values since that process incurs a lot of | ||
99 | * copying. | ||
100 | * | ||
101 | * info - describes the array | ||
102 | * root - the root block of the array on disk | ||
103 | * size - the number of entries in the array | ||
104 | * fn - the callback | ||
105 | * context - passed to the callback | ||
106 | */ | ||
107 | typedef int (*bit_value_fn)(uint32_t index, bool *value, void *context); | ||
108 | int dm_bitset_new(struct dm_disk_bitset *info, dm_block_t *root, | ||
109 | uint32_t size, bit_value_fn fn, void *context); | ||
110 | |||
111 | /* | ||
96 | * Resize the bitset. | 112 | * Resize the bitset. |
97 | * | 113 | * |
98 | * info - describes the bitset | 114 | * info - describes the bitset |