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