1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015 Google, Inc.
5 * Author: Sami Tolvanen <samitolvanen@google.com>
8 #include "dm-verity-fec.h"
9 #include <linux/math64.h>
11 #define DM_MSG_PREFIX "verity-fec"
14 * If error correction has been configured, returns true.
16 bool verity_fec_is_enabled(struct dm_verity
*v
)
18 return v
->fec
&& v
->fec
->dev
;
22 * Return a pointer to dm_verity_fec_io after dm_verity_io and its variable
25 static inline struct dm_verity_fec_io
*fec_io(struct dm_verity_io
*io
)
27 return (struct dm_verity_fec_io
*)
28 ((char *)io
+ io
->v
->ti
->per_io_data_size
- sizeof(struct dm_verity_fec_io
));
32 * Return an interleaved offset for a byte in RS block.
34 static inline u64
fec_interleave(struct dm_verity
*v
, u64 offset
)
38 mod
= do_div(offset
, v
->fec
->rsn
);
39 return offset
+ mod
* (v
->fec
->rounds
<< v
->data_dev_block_bits
);
43 * Decode an RS block using Reed-Solomon.
45 static int fec_decode_rs8(struct dm_verity
*v
, struct dm_verity_fec_io
*fio
,
46 u8
*data
, u8
*fec
, int neras
)
49 uint16_t par
[DM_VERITY_FEC_RSM
- DM_VERITY_FEC_MIN_RSN
];
51 for (i
= 0; i
< v
->fec
->roots
; i
++)
54 return decode_rs8(fio
->rs
, data
, par
, v
->fec
->rsn
, NULL
, neras
,
55 fio
->erasures
, 0, NULL
);
59 * Read error-correcting codes for the requested RS block. Returns a pointer
60 * to the data block. Caller is responsible for releasing buf.
62 static u8
*fec_read_parity(struct dm_verity
*v
, u64 rsb
, int index
,
63 unsigned int *offset
, struct dm_buffer
**buf
,
64 unsigned short ioprio
)
66 u64 position
, block
, rem
;
69 position
= (index
+ rsb
) * v
->fec
->roots
;
70 block
= div64_u64_rem(position
, v
->fec
->io_size
, &rem
);
71 *offset
= (unsigned int)rem
;
73 res
= dm_bufio_read_with_ioprio(v
->fec
->bufio
, block
, buf
, ioprio
);
75 DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
76 v
->data_dev
->name
, (unsigned long long)rsb
,
77 (unsigned long long)block
, PTR_ERR(res
));
84 /* Loop over each preallocated buffer slot. */
85 #define fec_for_each_prealloc_buffer(__i) \
86 for (__i = 0; __i < DM_VERITY_FEC_BUF_PREALLOC; __i++)
88 /* Loop over each extra buffer slot. */
89 #define fec_for_each_extra_buffer(io, __i) \
90 for (__i = DM_VERITY_FEC_BUF_PREALLOC; __i < DM_VERITY_FEC_BUF_MAX; __i++)
92 /* Loop over each allocated buffer. */
93 #define fec_for_each_buffer(io, __i) \
94 for (__i = 0; __i < (io)->nbufs; __i++)
96 /* Loop over each RS block in each allocated buffer. */
97 #define fec_for_each_buffer_rs_block(io, __i, __j) \
98 fec_for_each_buffer(io, __i) \
99 for (__j = 0; __j < 1 << DM_VERITY_FEC_BUF_RS_BITS; __j++)
102 * Return a pointer to the current RS block when called inside
103 * fec_for_each_buffer_rs_block.
105 static inline u8
*fec_buffer_rs_block(struct dm_verity
*v
,
106 struct dm_verity_fec_io
*fio
,
107 unsigned int i
, unsigned int j
)
109 return &fio
->bufs
[i
][j
* v
->fec
->rsn
];
113 * Return an index to the current RS block when called inside
114 * fec_for_each_buffer_rs_block.
116 static inline unsigned int fec_buffer_rs_index(unsigned int i
, unsigned int j
)
118 return (i
<< DM_VERITY_FEC_BUF_RS_BITS
) + j
;
122 * Decode all RS blocks from buffers and copy corrected bytes into fio->output
123 * starting from block_offset.
125 static int fec_decode_bufs(struct dm_verity
*v
, struct dm_verity_io
*io
,
126 struct dm_verity_fec_io
*fio
, u64 rsb
, int byte_index
,
127 unsigned int block_offset
, int neras
)
129 int r
, corrected
= 0, res
;
130 struct dm_buffer
*buf
;
131 unsigned int n
, i
, offset
;
133 struct bio
*bio
= dm_bio_from_per_bio_data(io
, v
->ti
->per_io_data_size
);
135 par
= fec_read_parity(v
, rsb
, block_offset
, &offset
, &buf
, bio_prio(bio
));
140 * Decode the RS blocks we have in bufs. Each RS block results in
141 * one corrected target byte and consumes fec->roots parity bytes.
143 fec_for_each_buffer_rs_block(fio
, n
, i
) {
144 block
= fec_buffer_rs_block(v
, fio
, n
, i
);
145 res
= fec_decode_rs8(v
, fio
, block
, &par
[offset
], neras
);
152 fio
->output
[block_offset
] = block
[byte_index
];
155 if (block_offset
>= 1 << v
->data_dev_block_bits
)
158 /* read the next block when we run out of parity bytes */
159 offset
+= v
->fec
->roots
;
160 if (offset
>= v
->fec
->io_size
) {
161 dm_bufio_release(buf
);
163 par
= fec_read_parity(v
, rsb
, block_offset
, &offset
, &buf
, bio_prio(bio
));
171 dm_bufio_release(buf
);
174 DMERR_LIMIT("%s: FEC %llu: failed to correct: %d",
175 v
->data_dev
->name
, (unsigned long long)rsb
, r
);
177 DMWARN_LIMIT("%s: FEC %llu: corrected %d errors",
178 v
->data_dev
->name
, (unsigned long long)rsb
, r
);
184 * Locate data block erasures using verity hashes.
186 static int fec_is_erasure(struct dm_verity
*v
, struct dm_verity_io
*io
,
187 u8
*want_digest
, u8
*data
)
189 if (unlikely(verity_hash(v
, io
, data
, 1 << v
->data_dev_block_bits
,
190 verity_io_real_digest(v
, io
), true)))
193 return memcmp(verity_io_real_digest(v
, io
), want_digest
,
194 v
->digest_size
) != 0;
198 * Read data blocks that are part of the RS block and deinterleave as much as
199 * fits into buffers. Check for erasure locations if @neras is non-NULL.
201 static int fec_read_bufs(struct dm_verity
*v
, struct dm_verity_io
*io
,
202 u64 rsb
, u64 target
, unsigned int block_offset
,
206 int i
, j
, target_index
= -1;
207 struct dm_buffer
*buf
;
208 struct dm_bufio_client
*bufio
;
209 struct dm_verity_fec_io
*fio
= fec_io(io
);
212 u8 want_digest
[HASH_MAX_DIGESTSIZE
];
214 struct bio
*bio
= dm_bio_from_per_bio_data(io
, v
->ti
->per_io_data_size
);
219 if (WARN_ON(v
->digest_size
> sizeof(want_digest
)))
223 * read each of the rsn data blocks that are part of the RS block, and
224 * interleave contents to available bufs
226 for (i
= 0; i
< v
->fec
->rsn
; i
++) {
227 ileaved
= fec_interleave(v
, rsb
* v
->fec
->rsn
+ i
);
230 * target is the data block we want to correct, target_index is
231 * the index of this block within the rsn RS blocks
233 if (ileaved
== target
)
236 block
= ileaved
>> v
->data_dev_block_bits
;
237 bufio
= v
->fec
->data_bufio
;
239 if (block
>= v
->data_blocks
) {
240 block
-= v
->data_blocks
;
243 * blocks outside the area were assumed to contain
244 * zeros when encoding data was generated
246 if (unlikely(block
>= v
->fec
->hash_blocks
))
249 block
+= v
->hash_start
;
253 bbuf
= dm_bufio_read_with_ioprio(bufio
, block
, &buf
, bio_prio(bio
));
255 DMWARN_LIMIT("%s: FEC %llu: read failed (%llu): %ld",
257 (unsigned long long)rsb
,
258 (unsigned long long)block
, PTR_ERR(bbuf
));
260 /* assume the block is corrupted */
261 if (neras
&& *neras
<= v
->fec
->roots
)
262 fio
->erasures
[(*neras
)++] = i
;
267 /* locate erasures if the block is on the data device */
268 if (bufio
== v
->fec
->data_bufio
&&
269 verity_hash_for_block(v
, io
, block
, want_digest
,
271 /* skip known zero blocks entirely */
276 * skip if we have already found the theoretical
277 * maximum number (i.e. fec->roots) of erasures
279 if (neras
&& *neras
<= v
->fec
->roots
&&
280 fec_is_erasure(v
, io
, want_digest
, bbuf
))
281 fio
->erasures
[(*neras
)++] = i
;
285 * deinterleave and copy the bytes that fit into bufs,
286 * starting from block_offset
288 fec_for_each_buffer_rs_block(fio
, n
, j
) {
289 k
= fec_buffer_rs_index(n
, j
) + block_offset
;
291 if (k
>= 1 << v
->data_dev_block_bits
)
294 rs_block
= fec_buffer_rs_block(v
, fio
, n
, j
);
295 rs_block
[i
] = bbuf
[k
];
298 dm_bufio_release(buf
);
305 * Allocate RS control structure and FEC buffers from preallocated mempools,
306 * and attempt to allocate as many extra buffers as available.
308 static int fec_alloc_bufs(struct dm_verity
*v
, struct dm_verity_fec_io
*fio
)
313 fio
->rs
= mempool_alloc(&v
->fec
->rs_pool
, GFP_NOIO
);
315 fec_for_each_prealloc_buffer(n
) {
319 fio
->bufs
[n
] = mempool_alloc(&v
->fec
->prealloc_pool
, GFP_NOWAIT
);
320 if (unlikely(!fio
->bufs
[n
])) {
321 DMERR("failed to allocate FEC buffer");
326 /* try to allocate the maximum number of buffers */
327 fec_for_each_extra_buffer(fio
, n
) {
331 fio
->bufs
[n
] = mempool_alloc(&v
->fec
->extra_pool
, GFP_NOWAIT
);
332 /* we can manage with even one buffer if necessary */
333 if (unlikely(!fio
->bufs
[n
]))
339 fio
->output
= mempool_alloc(&v
->fec
->output_pool
, GFP_NOIO
);
345 * Initialize buffers and clear erasures. fec_read_bufs() assumes buffers are
346 * zeroed before deinterleaving.
348 static void fec_init_bufs(struct dm_verity
*v
, struct dm_verity_fec_io
*fio
)
352 fec_for_each_buffer(fio
, n
)
353 memset(fio
->bufs
[n
], 0, v
->fec
->rsn
<< DM_VERITY_FEC_BUF_RS_BITS
);
355 memset(fio
->erasures
, 0, sizeof(fio
->erasures
));
359 * Decode all RS blocks in a single data block and return the target block
360 * (indicated by @offset) in fio->output. If @use_erasures is non-zero, uses
361 * hashes to locate erasures.
363 static int fec_decode_rsb(struct dm_verity
*v
, struct dm_verity_io
*io
,
364 struct dm_verity_fec_io
*fio
, u64 rsb
, u64 offset
,
370 r
= fec_alloc_bufs(v
, fio
);
374 for (pos
= 0; pos
< 1 << v
->data_dev_block_bits
; ) {
375 fec_init_bufs(v
, fio
);
377 r
= fec_read_bufs(v
, io
, rsb
, offset
, pos
,
378 use_erasures
? &neras
: NULL
);
382 r
= fec_decode_bufs(v
, io
, fio
, rsb
, r
, pos
, neras
);
386 pos
+= fio
->nbufs
<< DM_VERITY_FEC_BUF_RS_BITS
;
389 /* Always re-validate the corrected block against the expected hash */
390 r
= verity_hash(v
, io
, fio
->output
, 1 << v
->data_dev_block_bits
,
391 verity_io_real_digest(v
, io
), true);
395 if (memcmp(verity_io_real_digest(v
, io
), verity_io_want_digest(v
, io
),
397 DMERR_LIMIT("%s: FEC %llu: failed to correct (%d erasures)",
398 v
->data_dev
->name
, (unsigned long long)rsb
, neras
);
405 /* Correct errors in a block. Copies corrected block to dest. */
406 int verity_fec_decode(struct dm_verity
*v
, struct dm_verity_io
*io
,
407 enum verity_block_type type
, sector_t block
, u8
*dest
)
410 struct dm_verity_fec_io
*fio
= fec_io(io
);
411 u64 offset
, res
, rsb
;
413 if (!verity_fec_is_enabled(v
))
416 if (fio
->level
>= DM_VERITY_FEC_MAX_RECURSION
) {
417 DMWARN_LIMIT("%s: FEC: recursion too deep", v
->data_dev
->name
);
423 if (type
== DM_VERITY_BLOCK_TYPE_METADATA
)
424 block
= block
- v
->hash_start
+ v
->data_blocks
;
427 * For RS(M, N), the continuous FEC data is divided into blocks of N
428 * bytes. Since block size may not be divisible by N, the last block
429 * is zero padded when decoding.
431 * Each byte of the block is covered by a different RS(M, N) code,
432 * and each code is interleaved over N blocks to make it less likely
433 * that bursty corruption will leave us in unrecoverable state.
436 offset
= block
<< v
->data_dev_block_bits
;
437 res
= div64_u64(offset
, v
->fec
->rounds
<< v
->data_dev_block_bits
);
440 * The base RS block we can feed to the interleaver to find out all
441 * blocks required for decoding.
443 rsb
= offset
- res
* (v
->fec
->rounds
<< v
->data_dev_block_bits
);
446 * Locating erasures is slow, so attempt to recover the block without
447 * them first. Do a second attempt with erasures if the corruption is
450 r
= fec_decode_rsb(v
, io
, fio
, rsb
, offset
, false);
452 r
= fec_decode_rsb(v
, io
, fio
, rsb
, offset
, true);
457 memcpy(dest
, fio
->output
, 1 << v
->data_dev_block_bits
);
465 * Clean up per-bio data.
467 void verity_fec_finish_io(struct dm_verity_io
*io
)
470 struct dm_verity_fec
*f
= io
->v
->fec
;
471 struct dm_verity_fec_io
*fio
= fec_io(io
);
473 if (!verity_fec_is_enabled(io
->v
))
476 mempool_free(fio
->rs
, &f
->rs_pool
);
478 fec_for_each_prealloc_buffer(n
)
479 mempool_free(fio
->bufs
[n
], &f
->prealloc_pool
);
481 fec_for_each_extra_buffer(fio
, n
)
482 mempool_free(fio
->bufs
[n
], &f
->extra_pool
);
484 mempool_free(fio
->output
, &f
->output_pool
);
488 * Initialize per-bio data.
490 void verity_fec_init_io(struct dm_verity_io
*io
)
492 struct dm_verity_fec_io
*fio
= fec_io(io
);
494 if (!verity_fec_is_enabled(io
->v
))
498 memset(fio
->bufs
, 0, sizeof(fio
->bufs
));
505 * Append feature arguments and values to the status table.
507 unsigned int verity_fec_status_table(struct dm_verity
*v
, unsigned int sz
,
508 char *result
, unsigned int maxlen
)
510 if (!verity_fec_is_enabled(v
))
513 DMEMIT(" " DM_VERITY_OPT_FEC_DEV
" %s "
514 DM_VERITY_OPT_FEC_BLOCKS
" %llu "
515 DM_VERITY_OPT_FEC_START
" %llu "
516 DM_VERITY_OPT_FEC_ROOTS
" %d",
518 (unsigned long long)v
->fec
->blocks
,
519 (unsigned long long)v
->fec
->start
,
525 void verity_fec_dtr(struct dm_verity
*v
)
527 struct dm_verity_fec
*f
= v
->fec
;
529 if (!verity_fec_is_enabled(v
))
532 mempool_exit(&f
->rs_pool
);
533 mempool_exit(&f
->prealloc_pool
);
534 mempool_exit(&f
->extra_pool
);
535 mempool_exit(&f
->output_pool
);
536 kmem_cache_destroy(f
->cache
);
539 dm_bufio_client_destroy(f
->data_bufio
);
541 dm_bufio_client_destroy(f
->bufio
);
544 dm_put_device(v
->ti
, f
->dev
);
550 static void *fec_rs_alloc(gfp_t gfp_mask
, void *pool_data
)
552 struct dm_verity
*v
= pool_data
;
554 return init_rs_gfp(8, 0x11d, 0, 1, v
->fec
->roots
, gfp_mask
);
557 static void fec_rs_free(void *element
, void *pool_data
)
559 struct rs_control
*rs
= element
;
565 bool verity_is_fec_opt_arg(const char *arg_name
)
567 return (!strcasecmp(arg_name
, DM_VERITY_OPT_FEC_DEV
) ||
568 !strcasecmp(arg_name
, DM_VERITY_OPT_FEC_BLOCKS
) ||
569 !strcasecmp(arg_name
, DM_VERITY_OPT_FEC_START
) ||
570 !strcasecmp(arg_name
, DM_VERITY_OPT_FEC_ROOTS
));
573 int verity_fec_parse_opt_args(struct dm_arg_set
*as
, struct dm_verity
*v
,
574 unsigned int *argc
, const char *arg_name
)
577 struct dm_target
*ti
= v
->ti
;
578 const char *arg_value
;
579 unsigned long long num_ll
;
584 ti
->error
= "FEC feature arguments require a value";
588 arg_value
= dm_shift_arg(as
);
591 if (!strcasecmp(arg_name
, DM_VERITY_OPT_FEC_DEV
)) {
592 r
= dm_get_device(ti
, arg_value
, BLK_OPEN_READ
, &v
->fec
->dev
);
594 ti
->error
= "FEC device lookup failed";
598 } else if (!strcasecmp(arg_name
, DM_VERITY_OPT_FEC_BLOCKS
)) {
599 if (sscanf(arg_value
, "%llu%c", &num_ll
, &dummy
) != 1 ||
600 ((sector_t
)(num_ll
<< (v
->data_dev_block_bits
- SECTOR_SHIFT
))
601 >> (v
->data_dev_block_bits
- SECTOR_SHIFT
) != num_ll
)) {
602 ti
->error
= "Invalid " DM_VERITY_OPT_FEC_BLOCKS
;
605 v
->fec
->blocks
= num_ll
;
607 } else if (!strcasecmp(arg_name
, DM_VERITY_OPT_FEC_START
)) {
608 if (sscanf(arg_value
, "%llu%c", &num_ll
, &dummy
) != 1 ||
609 ((sector_t
)(num_ll
<< (v
->data_dev_block_bits
- SECTOR_SHIFT
)) >>
610 (v
->data_dev_block_bits
- SECTOR_SHIFT
) != num_ll
)) {
611 ti
->error
= "Invalid " DM_VERITY_OPT_FEC_START
;
614 v
->fec
->start
= num_ll
;
616 } else if (!strcasecmp(arg_name
, DM_VERITY_OPT_FEC_ROOTS
)) {
617 if (sscanf(arg_value
, "%hhu%c", &num_c
, &dummy
) != 1 || !num_c
||
618 num_c
< (DM_VERITY_FEC_RSM
- DM_VERITY_FEC_MAX_RSN
) ||
619 num_c
> (DM_VERITY_FEC_RSM
- DM_VERITY_FEC_MIN_RSN
)) {
620 ti
->error
= "Invalid " DM_VERITY_OPT_FEC_ROOTS
;
623 v
->fec
->roots
= num_c
;
626 ti
->error
= "Unrecognized verity FEC feature request";
634 * Allocate dm_verity_fec for v->fec. Must be called before verity_fec_ctr.
636 int verity_fec_ctr_alloc(struct dm_verity
*v
)
638 struct dm_verity_fec
*f
;
640 f
= kzalloc(sizeof(struct dm_verity_fec
), GFP_KERNEL
);
642 v
->ti
->error
= "Cannot allocate FEC structure";
651 * Validate arguments and preallocate memory. Must be called after arguments
652 * have been parsed using verity_fec_parse_opt_args.
654 int verity_fec_ctr(struct dm_verity
*v
)
656 struct dm_verity_fec
*f
= v
->fec
;
657 struct dm_target
*ti
= v
->ti
;
658 u64 hash_blocks
, fec_blocks
;
661 if (!verity_fec_is_enabled(v
)) {
667 * FEC is computed over data blocks, possible metadata, and
668 * hash blocks. In other words, FEC covers total of fec_blocks
669 * blocks consisting of the following:
671 * data blocks | hash blocks | metadata (optional)
673 * We allow metadata after hash blocks to support a use case
674 * where all data is stored on the same device and FEC covers
677 * If metadata is included, we require it to be available on the
678 * hash device after the hash blocks.
681 hash_blocks
= v
->hash_blocks
- v
->hash_start
;
684 * Require matching block sizes for data and hash devices for
687 if (v
->data_dev_block_bits
!= v
->hash_dev_block_bits
) {
688 ti
->error
= "Block sizes must match to use FEC";
693 ti
->error
= "Missing " DM_VERITY_OPT_FEC_ROOTS
;
696 f
->rsn
= DM_VERITY_FEC_RSM
- f
->roots
;
699 ti
->error
= "Missing " DM_VERITY_OPT_FEC_BLOCKS
;
703 f
->rounds
= f
->blocks
;
704 if (sector_div(f
->rounds
, f
->rsn
))
708 * Due to optional metadata, f->blocks can be larger than
709 * data_blocks and hash_blocks combined.
711 if (f
->blocks
< v
->data_blocks
+ hash_blocks
|| !f
->rounds
) {
712 ti
->error
= "Invalid " DM_VERITY_OPT_FEC_BLOCKS
;
717 * Metadata is accessed through the hash device, so we require
718 * it to be large enough.
720 f
->hash_blocks
= f
->blocks
- v
->data_blocks
;
721 if (dm_bufio_get_device_size(v
->bufio
) < f
->hash_blocks
) {
722 ti
->error
= "Hash device is too small for "
723 DM_VERITY_OPT_FEC_BLOCKS
;
727 if ((f
->roots
<< SECTOR_SHIFT
) & ((1 << v
->data_dev_block_bits
) - 1))
728 f
->io_size
= 1 << v
->data_dev_block_bits
;
730 f
->io_size
= v
->fec
->roots
<< SECTOR_SHIFT
;
732 f
->bufio
= dm_bufio_client_create(f
->dev
->bdev
,
734 1, 0, NULL
, NULL
, 0);
735 if (IS_ERR(f
->bufio
)) {
736 ti
->error
= "Cannot initialize FEC bufio client";
737 return PTR_ERR(f
->bufio
);
740 dm_bufio_set_sector_offset(f
->bufio
, f
->start
<< (v
->data_dev_block_bits
- SECTOR_SHIFT
));
742 fec_blocks
= div64_u64(f
->rounds
* f
->roots
, v
->fec
->roots
<< SECTOR_SHIFT
);
743 if (dm_bufio_get_device_size(f
->bufio
) < fec_blocks
) {
744 ti
->error
= "FEC device is too small";
748 f
->data_bufio
= dm_bufio_client_create(v
->data_dev
->bdev
,
749 1 << v
->data_dev_block_bits
,
750 1, 0, NULL
, NULL
, 0);
751 if (IS_ERR(f
->data_bufio
)) {
752 ti
->error
= "Cannot initialize FEC data bufio client";
753 return PTR_ERR(f
->data_bufio
);
756 if (dm_bufio_get_device_size(f
->data_bufio
) < v
->data_blocks
) {
757 ti
->error
= "Data device is too small";
761 /* Preallocate an rs_control structure for each worker thread */
762 ret
= mempool_init(&f
->rs_pool
, num_online_cpus(), fec_rs_alloc
,
763 fec_rs_free
, (void *) v
);
765 ti
->error
= "Cannot allocate RS pool";
769 f
->cache
= kmem_cache_create("dm_verity_fec_buffers",
770 f
->rsn
<< DM_VERITY_FEC_BUF_RS_BITS
,
773 ti
->error
= "Cannot create FEC buffer cache";
777 /* Preallocate DM_VERITY_FEC_BUF_PREALLOC buffers for each thread */
778 ret
= mempool_init_slab_pool(&f
->prealloc_pool
, num_online_cpus() *
779 DM_VERITY_FEC_BUF_PREALLOC
,
782 ti
->error
= "Cannot allocate FEC buffer prealloc pool";
786 ret
= mempool_init_slab_pool(&f
->extra_pool
, 0, f
->cache
);
788 ti
->error
= "Cannot allocate FEC buffer extra pool";
792 /* Preallocate an output buffer for each thread */
793 ret
= mempool_init_kmalloc_pool(&f
->output_pool
, num_online_cpus(),
794 1 << v
->data_dev_block_bits
);
796 ti
->error
= "Cannot allocate FEC output pool";
800 /* Reserve space for our per-bio data */
801 ti
->per_io_data_size
+= sizeof(struct dm_verity_fec_io
);