Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/log.h"
7 : : #include "spdk/util.h"
8 : :
9 : : #include "ftl_bitmap.h"
10 : : #include "ftl_internal.h"
11 : :
12 : : typedef unsigned long bitmap_word;
13 : :
14 : : const size_t ftl_bitmap_buffer_alignment = sizeof(bitmap_word);
15 : :
16 : : #define FTL_BITMAP_WORD_SHIFT spdk_u32log2(sizeof(bitmap_word) * 8)
17 : : #define FTL_BITMAP_WORD_MASK (~(~0UL << FTL_BITMAP_WORD_SHIFT))
18 : :
19 : : uint64_t
20 : 27 : ftl_bitmap_bits_to_size(uint64_t bits)
21 : : {
22 : : uint64_t size;
23 : :
24 [ - + ]: 27 : if (bits < ftl_bitmap_buffer_alignment) {
25 : 0 : bits = ftl_bitmap_buffer_alignment;
26 : : }
27 : :
28 : 27 : size = spdk_divide_round_up(bits, 8);
29 : 27 : size = spdk_divide_round_up(size, ftl_bitmap_buffer_alignment) * ftl_bitmap_buffer_alignment;
30 : :
31 : 27 : return size;
32 : : }
33 : :
34 : : uint64_t
35 : 27 : ftl_bitmap_bits_to_blocks(uint64_t bits)
36 : : {
37 : 27 : uint64_t size = ftl_bitmap_bits_to_size(bits);
38 : :
39 : 27 : return spdk_divide_round_up(size, FTL_BLOCK_SIZE);
40 : : }
41 : :
42 : : struct ftl_bitmap {
43 : : bitmap_word *buf;
44 : : size_t size;
45 : : };
46 : :
47 : 2767 : struct ftl_bitmap *ftl_bitmap_create(void *buf, size_t size)
48 : : {
49 : : struct ftl_bitmap *bitmap;
50 : :
51 [ + + + + ]: 2767 : if ((uintptr_t)buf % ftl_bitmap_buffer_alignment) {
52 : 5 : SPDK_ERRLOG("Buffer for bitmap must be aligned to %lu bytes\n",
53 : : ftl_bitmap_buffer_alignment);
54 : 5 : return NULL;
55 : : }
56 : :
57 [ + + + + ]: 2762 : if (size % ftl_bitmap_buffer_alignment) {
58 : 5 : SPDK_ERRLOG("Size of buffer for bitmap must be divisible by %lu bytes\n",
59 : : ftl_bitmap_buffer_alignment);
60 : 5 : return NULL;
61 : : }
62 : :
63 : 2757 : bitmap = calloc(1, sizeof(*bitmap));
64 [ - + ]: 2757 : if (!bitmap) {
65 : 0 : return NULL;
66 : : }
67 : :
68 : 2757 : bitmap->buf = buf;
69 : 2757 : bitmap->size = size / sizeof(bitmap_word);
70 : :
71 : 2757 : return bitmap;
72 : : }
73 : :
74 : : void
75 : 2752 : ftl_bitmap_destroy(struct ftl_bitmap *bitmap)
76 : : {
77 : 2752 : free(bitmap);
78 : 2752 : }
79 : :
80 : : static inline void
81 : 24471986 : locate_bit(const struct ftl_bitmap *bitmap, uint64_t bit,
82 : : bitmap_word **word_out, uint8_t *word_bit_idx_out)
83 : : {
84 [ - + ]: 24471986 : size_t word_idx = bit >> FTL_BITMAP_WORD_SHIFT;
85 : :
86 [ - + ]: 24471986 : assert(word_idx < bitmap->size);
87 : :
88 [ - + ]: 24471986 : *word_bit_idx_out = bit & FTL_BITMAP_WORD_MASK;
89 : 24471986 : *word_out = &bitmap->buf[word_idx];
90 : 24471986 : }
91 : :
92 : : bool
93 : 19679088 : ftl_bitmap_get(const struct ftl_bitmap *bitmap, uint64_t bit)
94 : : {
95 : 19677010 : bitmap_word *word;
96 : 19677010 : uint8_t word_bit_idx;
97 : :
98 : 19679088 : locate_bit(bitmap, bit, &word, &word_bit_idx);
99 : :
100 [ - + ]: 19679088 : return *word & (1UL << word_bit_idx);
101 : : }
102 : :
103 : : void
104 : 3423713 : ftl_bitmap_set(struct ftl_bitmap *bitmap, uint64_t bit)
105 : : {
106 : 3423683 : bitmap_word *word;
107 : 3423683 : uint8_t word_bit_idx;
108 : :
109 : 3423713 : locate_bit(bitmap, bit, &word, &word_bit_idx);
110 : :
111 [ - + ]: 3423713 : *word |= (1UL << word_bit_idx);
112 : 3423713 : }
113 : :
114 : : void
115 : 1369185 : ftl_bitmap_clear(struct ftl_bitmap *bitmap, uint64_t bit)
116 : : {
117 : 1369165 : bitmap_word *word;
118 : 1369165 : uint8_t word_bit_idx;
119 : :
120 : 1369185 : locate_bit(bitmap, bit, &word, &word_bit_idx);
121 : :
122 [ - + ]: 1369185 : *word &= ~(1UL << word_bit_idx);
123 : 1369185 : }
124 : :
125 : : static uint64_t
126 : 1056799 : ftl_bitmap_find_first(struct ftl_bitmap *bitmap, uint64_t start_bit,
127 : : uint64_t end_bit, bool value)
128 : : {
129 [ + + ]: 1056799 : bitmap_word skip = (value ? 0 : ~0UL);
130 : : bitmap_word word;
131 : : size_t i, end;
132 : : uint64_t ret;
133 : :
134 [ - + ]: 1056799 : assert(start_bit <= end_bit);
135 : :
136 [ - + ]: 1056799 : i = start_bit >> FTL_BITMAP_WORD_SHIFT;
137 [ - + ]: 1056799 : assert(i < bitmap->size);
138 : :
139 [ - + - + ]: 1056799 : word = (bitmap->buf[i] ^ skip) & (~0UL << (start_bit & FTL_BITMAP_WORD_MASK));
140 [ + + ]: 1056799 : if (word != 0) {
141 : 1056625 : goto found;
142 : : }
143 : :
144 [ + + + + : 174 : end = spdk_min((end_bit >> FTL_BITMAP_WORD_SHIFT) + 1, bitmap->size);
- + ]
145 [ + + ]: 27836 : for (i = i + 1; i < end; i++) {
146 : 27787 : word = bitmap->buf[i] ^ skip;
147 [ + + ]: 27787 : if (word != 0) {
148 : 125 : goto found;
149 : : }
150 : : }
151 : :
152 : 49 : return UINT64_MAX;
153 : 1056750 : found:
154 [ - + - + ]: 1056750 : ret = (i << FTL_BITMAP_WORD_SHIFT) + __builtin_ctzl(word);
155 [ + + ]: 1056750 : if (ret > end_bit) {
156 : 90 : return UINT64_MAX;
157 : : }
158 : 1056660 : return ret;
159 : : }
160 : :
161 : : uint64_t
162 : 1056549 : ftl_bitmap_find_first_set(struct ftl_bitmap *bitmap, uint64_t start_bit, uint64_t end_bit)
163 : : {
164 : 1056549 : return ftl_bitmap_find_first(bitmap, start_bit, end_bit, true);
165 : : }
166 : :
167 : : uint64_t
168 : 250 : ftl_bitmap_find_first_clear(struct ftl_bitmap *bitmap, uint64_t start_bit,
169 : : uint64_t end_bit)
170 : : {
171 : 250 : return ftl_bitmap_find_first(bitmap, start_bit, end_bit, false);
172 : : }
173 : :
174 : : uint64_t
175 : 2028 : ftl_bitmap_count_set(struct ftl_bitmap *bitmap)
176 : : {
177 : : size_t i;
178 : 2028 : bitmap_word *word = bitmap->buf;
179 : 2028 : uint64_t count = 0;
180 : :
181 [ + + ]: 8267836 : for (i = 0; i < bitmap->size; i++, word++) {
182 : 8265808 : count += __builtin_popcountl(*word);
183 : : }
184 : :
185 : 2028 : return count;
186 : : }
|