]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/include/spdk/dif.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / include / spdk / dif.h
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef SPDK_DIF_H
35 #define SPDK_DIF_H
36
37 #include "spdk/stdinc.h"
38 #include "spdk/assert.h"
39
40 #define SPDK_DIF_FLAGS_REFTAG_CHECK (1U << 26)
41 #define SPDK_DIF_FLAGS_APPTAG_CHECK (1U << 27)
42 #define SPDK_DIF_FLAGS_GUARD_CHECK (1U << 28)
43
44 #define SPDK_DIF_REFTAG_ERROR 0x1
45 #define SPDK_DIF_APPTAG_ERROR 0x2
46 #define SPDK_DIF_GUARD_ERROR 0x4
47 #define SPDK_DIF_DATA_ERROR 0x8
48
49 enum spdk_dif_type {
50 SPDK_DIF_DISABLE = 0,
51 SPDK_DIF_TYPE1 = 1,
52 SPDK_DIF_TYPE2 = 2,
53 SPDK_DIF_TYPE3 = 3,
54 };
55
56 enum spdk_dif_check_type {
57 SPDK_DIF_CHECK_TYPE_REFTAG = 1,
58 SPDK_DIF_CHECK_TYPE_APPTAG = 2,
59 SPDK_DIF_CHECK_TYPE_GUARD = 3,
60 };
61
62 struct spdk_dif {
63 uint16_t guard;
64 uint16_t app_tag;
65 uint32_t ref_tag;
66 };
67 SPDK_STATIC_ASSERT(sizeof(struct spdk_dif) == 8, "Incorrect size");
68
69 /** DIF context information */
70 struct spdk_dif_ctx {
71 /** Block size */
72 uint32_t block_size;
73
74 /** Metadata size */
75 uint32_t md_size;
76
77 /** Metadata location */
78 bool md_interleave;
79
80 /** Interval for guard computation for DIF */
81 uint32_t guard_interval;
82
83 /** DIF type */
84 enum spdk_dif_type dif_type;
85
86 /* Flags to specify the DIF action */
87 uint32_t dif_flags;
88
89 /* Initial reference tag */
90 uint32_t init_ref_tag;
91
92 /** Application tag */
93 uint16_t app_tag;
94
95 /* Application tag mask */
96 uint16_t apptag_mask;
97
98 /* Byte offset from the start of the whole data buffer. */
99 uint32_t data_offset;
100
101 /* Offset to initial reference tag */
102 uint32_t ref_tag_offset;
103
104 /** Guard value of the last data block.
105 *
106 * Interim guard value is set if the last data block is partial, or
107 * seed value is set otherwise.
108 */
109 uint16_t last_guard;
110
111 /* Seed value for guard computation */
112 uint16_t guard_seed;
113
114 /* Remapped initial reference tag. */
115 uint32_t remapped_init_ref_tag;
116 };
117
118 /** DIF error information */
119 struct spdk_dif_error {
120 /** Error type */
121 uint8_t err_type;
122
123 /** Expected value */
124 uint32_t expected;
125
126 /** Actual value */
127 uint32_t actual;
128
129 /** Offset the error occurred at, block based */
130 uint32_t err_offset;
131 };
132
133 /**
134 * Initialize DIF context.
135 *
136 * \param ctx DIF context.
137 * \param block_size Block size in a block.
138 * \param md_size Metadata size in a block.
139 * \param md_interleave If true, metadata is interleaved with block data.
140 * If false, metadata is separated with block data.
141 * \param dif_loc DIF location. If true, DIF is set in the first 8 bytes of metadata.
142 * If false, DIF is in the last 8 bytes of metadata.
143 * \param dif_type Type of DIF.
144 * \param dif_flags Flag to specify the DIF action.
145 * \param init_ref_tag Initial reference tag. For type 1, this is the
146 * starting block address.
147 * \param apptag_mask Application tag mask.
148 * \param app_tag Application tag.
149 * \param data_offset Byte offset from the start of the whole data buffer.
150 * \param guard_seed Seed value for guard computation.
151 *
152 * \return 0 on success and negated errno otherwise.
153 */
154 int spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size,
155 bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
156 uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
157 uint32_t data_offset, uint16_t guard_seed);
158
159 /**
160 * Update date offset of DIF context.
161 *
162 * \param ctx DIF context.
163 * \param data_offset Byte offset from the start of the whole data buffer.
164 */
165 void spdk_dif_ctx_set_data_offset(struct spdk_dif_ctx *ctx, uint32_t data_offset);
166
167 /**
168 * Set remapped initial reference tag of DIF context.
169 *
170 * \param ctx DIF context.
171 * \param remapped_init_ref_tag Remapped initial reference tag. For type 1, this is the
172 * starting block address.
173 */
174 void spdk_dif_ctx_set_remapped_init_ref_tag(struct spdk_dif_ctx *ctx,
175 uint32_t remapped_init_ref_tag);
176
177 /**
178 * Generate DIF for extended LBA payload.
179 *
180 * \param iovs iovec array describing the extended LBA payload.
181 * \param iovcnt Number of elements in the iovec array.
182 * \param num_blocks Number of blocks of the payload.
183 * \param ctx DIF context.
184 *
185 * \return 0 on success and negated errno otherwise.
186 */
187 int spdk_dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
188 const struct spdk_dif_ctx *ctx);
189
190 /**
191 * Verify DIF for extended LBA payload.
192 *
193 * \param iovs iovec array describing the extended LBA payload.
194 * \param iovcnt Number of elements in the iovec array.
195 * \param num_blocks Number of blocks of the payload.
196 * \param ctx DIF context.
197 * \param err_blk Error information of the block in which DIF error is found.
198 *
199 * \return 0 on success and negated errno otherwise.
200 */
201 int spdk_dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
202 const struct spdk_dif_ctx *ctx, struct spdk_dif_error *err_blk);
203
204 /**
205 * Calculate CRC-32C checksum for extended LBA payload.
206 *
207 * \param iovs iovec array describing the extended LBA payload.
208 * \param iovcnt Number of elements in the iovec array.
209 * \param num_blocks Number of blocks of the payload.
210 * \param crc32c Initial and updated CRC-32C value.
211 * \param ctx DIF context.
212 *
213 * \return 0 on success and negated errno otherwise.
214 */
215 int spdk_dif_update_crc32c(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
216 uint32_t *crc32c, const struct spdk_dif_ctx *ctx);
217
218 /**
219 * Copy data and generate DIF for extended LBA payload.
220 *
221 * \param iovs iovec array describing the LBA payload.
222 * \param iovcnt Number of elements in the iovec array.
223 * \param bounce_iov A contiguous buffer forming extended LBA payload.
224 * \param num_blocks Number of blocks of the LBA payload.
225 * \param ctx DIF context.
226 *
227 * \return 0 on success and negated errno otherwise.
228 */
229 int spdk_dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
230 uint32_t num_blocks, const struct spdk_dif_ctx *ctx);
231
232 /**
233 * Verify DIF and copy data for extended LBA payload.
234 *
235 * \param iovs iovec array describing the LBA payload.
236 * \param iovcnt Number of elements in the iovec array.
237 * \param bounce_iov A contiguous buffer forming extended LBA payload.
238 * \param num_blocks Number of blocks of the LBA payload.
239 * \param ctx DIF context.
240 * \param err_blk Error information of the block in which DIF error is found.
241 *
242 * \return 0 on success and negated errno otherwise.
243 */
244 int spdk_dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
245 uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
246 struct spdk_dif_error *err_blk);
247
248 /**
249 * Inject bit flip error to extended LBA payload.
250 *
251 * \param iovs iovec array describing the extended LBA payload.
252 * \param iovcnt Number of elements in the iovec array.
253 * \param num_blocks Number of blocks of the payload.
254 * \param ctx DIF context.
255 * \param inject_flags Flags to specify the action of error injection.
256 * \param inject_offset Offset, in blocks, to which error is injected.
257 * If multiple error is injected, only the last injection is stored.
258 *
259 * \return 0 on success and negated errno otherwise including no metadata.
260 */
261 int spdk_dif_inject_error(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
262 const struct spdk_dif_ctx *ctx, uint32_t inject_flags,
263 uint32_t *inject_offset);
264
265 /**
266 * Generate DIF for separate metadata payload.
267 *
268 * \param iovs iovec array describing the LBA payload.
269 * \params iovcnt Number of elements in iovs.
270 * \param md_iov A contiguous buffer for metadata.
271 * \param num_blocks Number of blocks of the separate metadata payload.
272 * \param ctx DIF context.
273 *
274 * \return 0 on success and negated errno otherwise.
275 */
276 int spdk_dix_generate(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
277 uint32_t num_blocks, const struct spdk_dif_ctx *ctx);
278
279 /**
280 * Verify DIF for separate metadata payload.
281 *
282 * \param iovs iovec array describing the LBA payload.
283 * \params iovcnt Number of elements in iovs.
284 * \param md_iov A contiguous buffer for metadata.
285 * \param num_blocks Number of blocks of the separate metadata payload.
286 * \param ctx DIF context.
287 * \param err_blk Error information of the block in which DIF error is found.
288 *
289 * \return 0 on success and negated errno otherwise.
290 */
291 int spdk_dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
292 uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
293 struct spdk_dif_error *err_blk);
294
295 /**
296 * Inject bit flip error to separate metadata payload.
297 *
298 * \param iovs iovec array describing the extended LBA payload.
299 * \param iovcnt Number of elements in the iovec array.
300 * \param md_iov A contiguous buffer for metadata.
301 * \param num_blocks Number of blocks of the payload.
302 * \param ctx DIF context.
303 * \param inject_flags Flag to specify the action of error injection.
304 * \param inject_offset Offset, in blocks, to which error is injected.
305 * If multiple error is injected, only the last injection is stored.
306 *
307 * \return 0 on success and negated errno otherwise including no metadata.
308 */
309 int spdk_dix_inject_error(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
310 uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
311 uint32_t inject_flags, uint32_t *inject_offset);
312
313 /**
314 * Setup iovec array to leave a space for metadata for each block.
315 *
316 * This function is used to leave a space for metadata for each block when
317 * the network socket reads data, or to make the network socket ignore a
318 * space for metadata for each block when the network socket writes data.
319 * This function removes the necessity of data copy in the SPDK application
320 * during DIF insertion and strip.
321 *
322 * When the extended LBA payload is splitted into multiple data segments,
323 * start of each data segment is passed through the DIF context. data_offset
324 * and data_len is within a data segment.
325 *
326 * \param iovs iovec array set by this function.
327 * \param iovcnt Number of elements in the iovec array.
328 * \param buf_iovs SGL for the buffer to create extended LBA payload.
329 * \param buf_iovcnt Size of the SGL for the buffer to create extended LBA payload.
330 * \param data_offset Offset to store the next incoming data in the current data segment.
331 * \param data_len Expected length of the newly read data in the current data segment of
332 * the extended LBA payload.
333 * \param mapped_len Output parameter that will contain data length mapped by
334 * the iovec array.
335 * \param ctx DIF context.
336 *
337 * \return Number of used elements in the iovec array on success or negated
338 * errno otherwise.
339 */
340 int spdk_dif_set_md_interleave_iovs(struct iovec *iovs, int iovcnt,
341 struct iovec *buf_iovs, int buf_iovcnt,
342 uint32_t data_offset, uint32_t data_len,
343 uint32_t *mapped_len,
344 const struct spdk_dif_ctx *ctx);
345
346 /**
347 * Generate and insert DIF into metadata space for newly read data block.
348 *
349 * When the extended LBA payload is splitted into multiple data segments,
350 * start of each data segment is passed through the DIF context. data_offset
351 * and data_len is within a data segment.
352 *
353 * \param iovs iovec array describing the extended LBA payload.
354 * \param iovcnt Number of elements in the iovec array.
355 * \param data_offset Offset to the newly read data in the current data segment of
356 * the extended LBA payload.
357 * \param data_len Length of the newly read data in the current data segment of
358 * the extended LBA payload.
359 * \param ctx DIF context.
360 *
361 * \return 0 on success and negated errno otherwise.
362 */
363 int spdk_dif_generate_stream(struct iovec *iovs, int iovcnt,
364 uint32_t data_offset, uint32_t data_len,
365 struct spdk_dif_ctx *ctx);
366
367 /**
368 * Verify DIF for the to-be-written block of the extended LBA payload.
369 *
370 * \param iovs iovec array describing the extended LBA payload.
371 * \param iovcnt Number of elements in the iovec array.
372 * \param data_offset Offset to the to-be-written data in the extended LBA payload.
373 * \param data_len Length of the to-be-written data in the extended LBA payload.
374 * \param ctx DIF context.
375 *
376 * \return 0 on success and negated errno otherwise.
377 */
378 int spdk_dif_verify_stream(struct iovec *iovs, int iovcnt,
379 uint32_t data_offset, uint32_t data_len,
380 struct spdk_dif_ctx *ctx,
381 struct spdk_dif_error *err_blk);
382
383 /**
384 * Calculate CRC-32C checksum of the specified range in the extended LBA payload.
385 *
386 * \param iovs iovec array describing the extended LBA payload.
387 * \param iovcnt Number of elements in the iovec array.
388 * \param data_offset Offset to the range
389 * \param data_len Length of the range
390 * \param crc32c Initial and updated CRC-32C value.
391 * \param ctx DIF context.
392 *
393 * \return 0 on success and negated errno otherwise.
394 */
395 int spdk_dif_update_crc32c_stream(struct iovec *iovs, int iovcnt,
396 uint32_t data_offset, uint32_t data_len,
397 uint32_t *crc32c, const struct spdk_dif_ctx *ctx);
398 /**
399 * Convert offset and size from LBA based to extended LBA based.
400 *
401 * \param data_offset Data offset
402 * \param data_len Data length
403 * \param buf_offset Buffer offset converted from data offset.
404 * \param buf_len Buffer length converted from data length
405 * \param ctx DIF context.
406 */
407 void spdk_dif_get_range_with_md(uint32_t data_offset, uint32_t data_len,
408 uint32_t *buf_offset, uint32_t *buf_len,
409 const struct spdk_dif_ctx *ctx);
410
411 /**
412 * Convert length from LBA based to extended LBA based.
413 *
414 * \param data_len Data length
415 * \param ctx DIF context.
416 *
417 * \return Extended LBA based data length.
418 */
419 uint32_t spdk_dif_get_length_with_md(uint32_t data_len, const struct spdk_dif_ctx *ctx);
420
421 /**
422 * Remap reference tag for extended LBA payload.
423 *
424 * When using stacked virtual bdev (e.g. split virtual bdev), block address space for I/O
425 * will be remapped during I/O processing and so reference tag will have to be remapped
426 * accordingly. This patch is for that case.
427 *
428 * \param iovs iovec array describing the extended LBA payload.
429 * \param iovcnt Number of elements in the iovec array.
430 * \param num_blocks Number of blocks of the payload.
431 * \param ctx DIF context.
432 * \param err_blk Error information of the block in which DIF error is found.
433 *
434 * \return 0 on success and negated errno otherwise.
435 */
436 int spdk_dif_remap_ref_tag(struct iovec *iovs, int iovcnt, uint32_t num_blocks,
437 const struct spdk_dif_ctx *dif_ctx,
438 struct spdk_dif_error *err_blk);
439
440 /**
441 * Remap reference tag for separate metadata payload.
442 *
443 * When using stacked virtual bdev (e.g. split virtual bdev), block address space for I/O
444 * will be remapped during I/O processing and so reference tag will have to be remapped
445 * accordingly. This patch is for that case.
446 *
447 * \param md_iov A contiguous buffer for metadata.
448 * \param num_blocks Number of blocks of the payload.
449 * \param ctx DIF context.
450 * \param err_blk Error information of the block in which DIF error is found.
451 *
452 * \return 0 on success and negated errno otherwise.
453 */
454 int spdk_dix_remap_ref_tag(struct iovec *md_iov, uint32_t num_blocks,
455 const struct spdk_dif_ctx *dif_ctx,
456 struct spdk_dif_error *err_blk);
457 #endif /* SPDK_DIF_H */