]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/Checksummer.h
update sources to v12.1.0
[ceph.git] / ceph / src / common / Checksummer.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_OS_BLUESTORE_CHECKSUMMER
5 #define CEPH_OS_BLUESTORE_CHECKSUMMER
6
7 #include "xxHash/xxhash.h"
8
9 class Checksummer {
10 public:
11 enum CSumType {
12 CSUM_NONE = 1, //intentionally set to 1 to be aligned with OSDMnitor's pool_opts_t handling - it treats 0 as unset while we need to distinguish none and unset cases
13 CSUM_XXHASH32 = 2,
14 CSUM_XXHASH64 = 3,
15 CSUM_CRC32C = 4,
16 CSUM_CRC32C_16 = 5, // low 16 bits of crc32c
17 CSUM_CRC32C_8 = 6, // low 8 bits of crc32c
18 CSUM_MAX,
19 };
20 static const char *get_csum_type_string(unsigned t) {
21 switch (t) {
22 case CSUM_NONE: return "none";
23 case CSUM_XXHASH32: return "xxhash32";
24 case CSUM_XXHASH64: return "xxhash64";
25 case CSUM_CRC32C: return "crc32c";
26 case CSUM_CRC32C_16: return "crc32c_16";
27 case CSUM_CRC32C_8: return "crc32c_8";
28 default: return "???";
29 }
30 }
31 static int get_csum_string_type(const std::string &s) {
32 if (s == "none")
33 return CSUM_NONE;
34 if (s == "xxhash32")
35 return CSUM_XXHASH32;
36 if (s == "xxhash64")
37 return CSUM_XXHASH64;
38 if (s == "crc32c")
39 return CSUM_CRC32C;
40 if (s == "crc32c_16")
41 return CSUM_CRC32C_16;
42 if (s == "crc32c_8")
43 return CSUM_CRC32C_8;
44 return -EINVAL;
45 }
46
47 static size_t get_csum_init_value_size(int csum_type) {
48 switch (csum_type) {
49 case CSUM_NONE: return 0;
50 case CSUM_XXHASH32: return sizeof(xxhash32::init_value_t);
51 case CSUM_XXHASH64: return sizeof(xxhash64::init_value_t);
52 case CSUM_CRC32C: return sizeof(crc32c::init_value_t);
53 case CSUM_CRC32C_16: return sizeof(crc32c_16::init_value_t);
54 case CSUM_CRC32C_8: return sizeof(crc32c_8::init_value_t);
55 default: return 0;
56 }
57 }
58 static size_t get_csum_value_size(int csum_type) {
59 switch (csum_type) {
60 case CSUM_NONE: return 0;
61 case CSUM_XXHASH32: return 4;
62 case CSUM_XXHASH64: return 8;
63 case CSUM_CRC32C: return 4;
64 case CSUM_CRC32C_16: return 2;
65 case CSUM_CRC32C_8: return 1;
66 default: return 0;
67 }
68 }
69
70 struct crc32c {
71 typedef uint32_t init_value_t;
72 typedef __le32 value_t;
73
74 // we have no execution context/state.
75 typedef int state_t;
76 static void init(state_t *state) {
77 }
78 static void fini(state_t *state) {
79 }
80
81 static value_t calc(
82 state_t state,
83 init_value_t init_value,
84 size_t len,
85 bufferlist::const_iterator& p
86 ) {
87 return p.crc32c(len, init_value);
88 }
89 };
90
91 struct crc32c_16 {
92 typedef uint32_t init_value_t;
93 typedef __le16 value_t;
94
95 // we have no execution context/state.
96 typedef int state_t;
97 static void init(state_t *state) {
98 }
99 static void fini(state_t *state) {
100 }
101
102 static value_t calc(
103 state_t state,
104 init_value_t init_value,
105 size_t len,
106 bufferlist::const_iterator& p
107 ) {
108 return p.crc32c(len, init_value) & 0xffff;
109 }
110 };
111
112 struct crc32c_8 {
113 typedef uint32_t init_value_t;
114 typedef __u8 value_t;
115
116 // we have no execution context/state.
117 typedef int state_t;
118 static void init(state_t *state) {
119 }
120 static void fini(state_t *state) {
121 }
122
123 static value_t calc(
124 state_t state,
125 init_value_t init_value,
126 size_t len,
127 bufferlist::const_iterator& p
128 ) {
129 return p.crc32c(len, init_value) & 0xff;
130 }
131 };
132
133 struct xxhash32 {
134 typedef uint32_t init_value_t;
135 typedef __le32 value_t;
136
137 typedef XXH32_state_t *state_t;
138 static void init(state_t *s) {
139 *s = XXH32_createState();
140 }
141 static void fini(state_t *s) {
142 XXH32_freeState(*s);
143 }
144
145 static value_t calc(
146 state_t state,
147 init_value_t init_value,
148 size_t len,
149 bufferlist::const_iterator& p
150 ) {
151 XXH32_reset(state, init_value);
152 while (len > 0) {
153 const char *data;
154 size_t l = p.get_ptr_and_advance(len, &data);
155 XXH32_update(state, data, l);
156 len -= l;
157 }
158 return XXH32_digest(state);
159 }
160 };
161
162 struct xxhash64 {
163 typedef uint64_t init_value_t;
164 typedef __le64 value_t;
165
166 typedef XXH64_state_t *state_t;
167 static void init(state_t *s) {
168 *s = XXH64_createState();
169 }
170 static void fini(state_t *s) {
171 XXH64_freeState(*s);
172 }
173
174 static value_t calc(
175 state_t state,
176 init_value_t init_value,
177 size_t len,
178 bufferlist::const_iterator& p
179 ) {
180 XXH64_reset(state, init_value);
181 while (len > 0) {
182 const char *data;
183 size_t l = p.get_ptr_and_advance(len, &data);
184 XXH64_update(state, data, l);
185 len -= l;
186 }
187 return XXH64_digest(state);
188 }
189 };
190
191 template<class Alg>
192 static int calculate(
193 size_t csum_block_size,
194 size_t offset,
195 size_t length,
196 const bufferlist &bl,
197 bufferptr* csum_data
198 ) {
199 return calculate<Alg>(-1, csum_block_size, offset, length, bl, csum_data);
200 }
201
202 template<class Alg>
203 static int calculate(
204 typename Alg::init_value_t init_value,
205 size_t csum_block_size,
206 size_t offset,
207 size_t length,
208 const bufferlist &bl,
209 bufferptr* csum_data) {
210 assert(length % csum_block_size == 0);
211 size_t blocks = length / csum_block_size;
212 bufferlist::const_iterator p = bl.begin();
213 assert(bl.length() >= length);
214
215 typename Alg::state_t state;
216 Alg::init(&state);
217
218 assert(csum_data->length() >= (offset + length) / csum_block_size *
219 sizeof(typename Alg::value_t));
220
221 typename Alg::value_t *pv =
222 reinterpret_cast<typename Alg::value_t*>(csum_data->c_str());
223 pv += offset / csum_block_size;
224 while (blocks--) {
225 *pv = Alg::calc(state, init_value, csum_block_size, p);
226 ++pv;
227 }
228 Alg::fini(&state);
229 return 0;
230 }
231
232 template<class Alg>
233 static int verify(
234 size_t csum_block_size,
235 size_t offset,
236 size_t length,
237 const bufferlist &bl,
238 const bufferptr& csum_data,
239 uint64_t *bad_csum=0
240 ) {
241 assert(length % csum_block_size == 0);
242 bufferlist::const_iterator p = bl.begin();
243 assert(bl.length() >= length);
244
245 typename Alg::state_t state;
246 Alg::init(&state);
247
248 const typename Alg::value_t *pv =
249 reinterpret_cast<const typename Alg::value_t*>(csum_data.c_str());
250 pv += offset / csum_block_size;
251 size_t pos = offset;
252 while (length > 0) {
253 typename Alg::value_t v = Alg::calc(state, -1, csum_block_size, p);
254 if (*pv != v) {
255 if (bad_csum) {
256 *bad_csum = v;
257 }
258 Alg::fini(&state);
259 return pos;
260 }
261 ++pv;
262 pos += csum_block_size;
263 length -= csum_block_size;
264 }
265 Alg::fini(&state);
266 return -1; // no errors
267 }
268 };
269
270 #endif