0001
0002
0003
0004
0005
0006
0007
0008 #include "dm-verity-fec.h"
0009 #include <linux/math64.h>
0010
0011 #define DM_MSG_PREFIX "verity-fec"
0012
0013
0014
0015
0016 bool verity_fec_is_enabled(struct dm_verity *v)
0017 {
0018 return v->fec && v->fec->dev;
0019 }
0020
0021
0022
0023
0024
0025 static inline struct dm_verity_fec_io *fec_io(struct dm_verity_io *io)
0026 {
0027 return (struct dm_verity_fec_io *) verity_io_digest_end(io->v, io);
0028 }
0029
0030
0031
0032
0033 static inline u64 fec_interleave(struct dm_verity *v, u64 offset)
0034 {
0035 u32 mod;
0036
0037 mod = do_div(offset, v->fec->rsn);
0038 return offset + mod * (v->fec->rounds << v->data_dev_block_bits);
0039 }
0040
0041
0042
0043
0044 static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
0045 u8 *data, u8 *fec, int neras)
0046 {
0047 int i;
0048 uint16_t par[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN];
0049
0050 for (i = 0; i < v->fec->roots; i++)
0051 par[i] = fec[i];
0052
0053 return decode_rs8(fio->rs, data, par, v->fec->rsn, NULL, neras,
0054 fio->erasures, 0, NULL);
0055 }
0056
0057
0058
0059
0060
0061 static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
0062 unsigned *offset, struct dm_buffer **buf)
0063 {
0064 u64 position, block, rem;
0065 u8 *res;
0066
0067 position = (index + rsb) * v->fec->roots;
0068 block = div64_u64_rem(position, v->fec->io_size, &rem);
0069 *offset = (unsigned)rem;
0070
0071 res = dm_bufio_read(v->fec->bufio, block, buf);
0072 if (IS_ERR(res)) {
0073 DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
0074 v->data_dev->name, (unsigned long long)rsb,
0075 (unsigned long long)block, PTR_ERR(res));
0076 *buf = NULL;
0077 }
0078
0079 return res;
0080 }
0081
0082
0083 #define fec_for_each_prealloc_buffer(__i) \
0084 for (__i = 0; __i < DM_VERITY_FEC_BUF_PREALLOC; __i++)
0085
0086
0087 #define fec_for_each_extra_buffer(io, __i) \
0088 for (__i = DM_VERITY_FEC_BUF_PREALLOC; __i < DM_VERITY_FEC_BUF_MAX; __i++)
0089
0090
0091 #define fec_for_each_buffer(io, __i) \
0092 for (__i = 0; __i < (io)->nbufs; __i++)
0093
0094
0095 #define fec_for_each_buffer_rs_block(io, __i, __j) \
0096 fec_for_each_buffer(io, __i) \
0097 for (__j = 0; __j < 1 << DM_VERITY_FEC_BUF_RS_BITS; __j++)
0098
0099
0100
0101
0102
0103 static inline u8 *fec_buffer_rs_block(struct dm_verity *v,
0104 struct dm_verity_fec_io *fio,
0105 unsigned i, unsigned j)
0106 {
0107 return &fio->bufs[i][j * v->fec->rsn];
0108 }
0109
0110
0111
0112
0113
0114 static inline unsigned fec_buffer_rs_index(unsigned i, unsigned j)
0115 {
0116 return (i << DM_VERITY_FEC_BUF_RS_BITS) + j;
0117 }
0118
0119
0120
0121
0122
0123 static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio,
0124 u64 rsb, int byte_index, unsigned block_offset,
0125 int neras)
0126 {
0127 int r, corrected = 0, res;
0128 struct dm_buffer *buf;
0129 unsigned n, i, offset;
0130 u8 *par, *block;
0131
0132 par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
0133 if (IS_ERR(par))
0134 return PTR_ERR(par);
0135
0136
0137
0138
0139
0140 fec_for_each_buffer_rs_block(fio, n, i) {
0141 block = fec_buffer_rs_block(v, fio, n, i);
0142 res = fec_decode_rs8(v, fio, block, &par[offset], neras);
0143 if (res < 0) {
0144 r = res;
0145 goto error;
0146 }
0147
0148 corrected += res;
0149 fio->output[block_offset] = block[byte_index];
0150
0151 block_offset++;
0152 if (block_offset >= 1 << v->data_dev_block_bits)
0153 goto done;
0154
0155
0156 offset += v->fec->roots;
0157 if (offset >= v->fec->io_size) {
0158 dm_bufio_release(buf);
0159
0160 par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
0161 if (IS_ERR(par))
0162 return PTR_ERR(par);
0163 }
0164 }
0165 done:
0166 r = corrected;
0167 error:
0168 dm_bufio_release(buf);
0169
0170 if (r < 0 && neras)
0171 DMERR_LIMIT("%s: FEC %llu: failed to correct: %d",
0172 v->data_dev->name, (unsigned long long)rsb, r);
0173 else if (r > 0)
0174 DMWARN_LIMIT("%s: FEC %llu: corrected %d errors",
0175 v->data_dev->name, (unsigned long long)rsb, r);
0176
0177 return r;
0178 }
0179
0180
0181
0182
0183 static int fec_is_erasure(struct dm_verity *v, struct dm_verity_io *io,
0184 u8 *want_digest, u8 *data)
0185 {
0186 if (unlikely(verity_hash(v, verity_io_hash_req(v, io),
0187 data, 1 << v->data_dev_block_bits,
0188 verity_io_real_digest(v, io))))
0189 return 0;
0190
0191 return memcmp(verity_io_real_digest(v, io), want_digest,
0192 v->digest_size) != 0;
0193 }
0194
0195
0196
0197
0198
0199 static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io,
0200 u64 rsb, u64 target, unsigned block_offset,
0201 int *neras)
0202 {
0203 bool is_zero;
0204 int i, j, target_index = -1;
0205 struct dm_buffer *buf;
0206 struct dm_bufio_client *bufio;
0207 struct dm_verity_fec_io *fio = fec_io(io);
0208 u64 block, ileaved;
0209 u8 *bbuf, *rs_block;
0210 u8 want_digest[HASH_MAX_DIGESTSIZE];
0211 unsigned n, k;
0212
0213 if (neras)
0214 *neras = 0;
0215
0216 if (WARN_ON(v->digest_size > sizeof(want_digest)))
0217 return -EINVAL;
0218
0219
0220
0221
0222
0223 for (i = 0; i < v->fec->rsn; i++) {
0224 ileaved = fec_interleave(v, rsb * v->fec->rsn + i);
0225
0226
0227
0228
0229
0230 if (ileaved == target)
0231 target_index = i;
0232
0233 block = ileaved >> v->data_dev_block_bits;
0234 bufio = v->fec->data_bufio;
0235
0236 if (block >= v->data_blocks) {
0237 block -= v->data_blocks;
0238
0239
0240
0241
0242
0243 if (unlikely(block >= v->fec->hash_blocks))
0244 continue;
0245
0246 block += v->hash_start;
0247 bufio = v->bufio;
0248 }
0249
0250 bbuf = dm_bufio_read(bufio, block, &buf);
0251 if (IS_ERR(bbuf)) {
0252 DMWARN_LIMIT("%s: FEC %llu: read failed (%llu): %ld",
0253 v->data_dev->name,
0254 (unsigned long long)rsb,
0255 (unsigned long long)block, PTR_ERR(bbuf));
0256
0257
0258 if (neras && *neras <= v->fec->roots)
0259 fio->erasures[(*neras)++] = i;
0260
0261 continue;
0262 }
0263
0264
0265 if (bufio == v->fec->data_bufio &&
0266 verity_hash_for_block(v, io, block, want_digest,
0267 &is_zero) == 0) {
0268
0269 if (is_zero)
0270 goto done;
0271
0272
0273
0274
0275
0276 if (neras && *neras <= v->fec->roots &&
0277 fec_is_erasure(v, io, want_digest, bbuf))
0278 fio->erasures[(*neras)++] = i;
0279 }
0280
0281
0282
0283
0284
0285 fec_for_each_buffer_rs_block(fio, n, j) {
0286 k = fec_buffer_rs_index(n, j) + block_offset;
0287
0288 if (k >= 1 << v->data_dev_block_bits)
0289 goto done;
0290
0291 rs_block = fec_buffer_rs_block(v, fio, n, j);
0292 rs_block[i] = bbuf[k];
0293 }
0294 done:
0295 dm_bufio_release(buf);
0296 }
0297
0298 return target_index;
0299 }
0300
0301
0302
0303
0304
0305 static int fec_alloc_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
0306 {
0307 unsigned n;
0308
0309 if (!fio->rs)
0310 fio->rs = mempool_alloc(&v->fec->rs_pool, GFP_NOIO);
0311
0312 fec_for_each_prealloc_buffer(n) {
0313 if (fio->bufs[n])
0314 continue;
0315
0316 fio->bufs[n] = mempool_alloc(&v->fec->prealloc_pool, GFP_NOWAIT);
0317 if (unlikely(!fio->bufs[n])) {
0318 DMERR("failed to allocate FEC buffer");
0319 return -ENOMEM;
0320 }
0321 }
0322
0323
0324 fec_for_each_extra_buffer(fio, n) {
0325 if (fio->bufs[n])
0326 continue;
0327
0328 fio->bufs[n] = mempool_alloc(&v->fec->extra_pool, GFP_NOWAIT);
0329
0330 if (unlikely(!fio->bufs[n]))
0331 break;
0332 }
0333 fio->nbufs = n;
0334
0335 if (!fio->output)
0336 fio->output = mempool_alloc(&v->fec->output_pool, GFP_NOIO);
0337
0338 return 0;
0339 }
0340
0341
0342
0343
0344
0345 static void fec_init_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio)
0346 {
0347 unsigned n;
0348
0349 fec_for_each_buffer(fio, n)
0350 memset(fio->bufs[n], 0, v->fec->rsn << DM_VERITY_FEC_BUF_RS_BITS);
0351
0352 memset(fio->erasures, 0, sizeof(fio->erasures));
0353 }
0354
0355
0356
0357
0358
0359
0360 static int fec_decode_rsb(struct dm_verity *v, struct dm_verity_io *io,
0361 struct dm_verity_fec_io *fio, u64 rsb, u64 offset,
0362 bool use_erasures)
0363 {
0364 int r, neras = 0;
0365 unsigned pos;
0366
0367 r = fec_alloc_bufs(v, fio);
0368 if (unlikely(r < 0))
0369 return r;
0370
0371 for (pos = 0; pos < 1 << v->data_dev_block_bits; ) {
0372 fec_init_bufs(v, fio);
0373
0374 r = fec_read_bufs(v, io, rsb, offset, pos,
0375 use_erasures ? &neras : NULL);
0376 if (unlikely(r < 0))
0377 return r;
0378
0379 r = fec_decode_bufs(v, fio, rsb, r, pos, neras);
0380 if (r < 0)
0381 return r;
0382
0383 pos += fio->nbufs << DM_VERITY_FEC_BUF_RS_BITS;
0384 }
0385
0386
0387 r = verity_hash(v, verity_io_hash_req(v, io), fio->output,
0388 1 << v->data_dev_block_bits,
0389 verity_io_real_digest(v, io));
0390 if (unlikely(r < 0))
0391 return r;
0392
0393 if (memcmp(verity_io_real_digest(v, io), verity_io_want_digest(v, io),
0394 v->digest_size)) {
0395 DMERR_LIMIT("%s: FEC %llu: failed to correct (%d erasures)",
0396 v->data_dev->name, (unsigned long long)rsb, neras);
0397 return -EILSEQ;
0398 }
0399
0400 return 0;
0401 }
0402
0403 static int fec_bv_copy(struct dm_verity *v, struct dm_verity_io *io, u8 *data,
0404 size_t len)
0405 {
0406 struct dm_verity_fec_io *fio = fec_io(io);
0407
0408 memcpy(data, &fio->output[fio->output_pos], len);
0409 fio->output_pos += len;
0410
0411 return 0;
0412 }
0413
0414
0415
0416
0417
0418 int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
0419 enum verity_block_type type, sector_t block, u8 *dest,
0420 struct bvec_iter *iter)
0421 {
0422 int r;
0423 struct dm_verity_fec_io *fio = fec_io(io);
0424 u64 offset, res, rsb;
0425
0426 if (!verity_fec_is_enabled(v))
0427 return -EOPNOTSUPP;
0428
0429 if (fio->level >= DM_VERITY_FEC_MAX_RECURSION) {
0430 DMWARN_LIMIT("%s: FEC: recursion too deep", v->data_dev->name);
0431 return -EIO;
0432 }
0433
0434 fio->level++;
0435
0436 if (type == DM_VERITY_BLOCK_TYPE_METADATA)
0437 block = block - v->hash_start + v->data_blocks;
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449 offset = block << v->data_dev_block_bits;
0450 res = div64_u64(offset, v->fec->rounds << v->data_dev_block_bits);
0451
0452
0453
0454
0455
0456 rsb = offset - res * (v->fec->rounds << v->data_dev_block_bits);
0457
0458
0459
0460
0461
0462
0463 r = fec_decode_rsb(v, io, fio, rsb, offset, false);
0464 if (r < 0) {
0465 r = fec_decode_rsb(v, io, fio, rsb, offset, true);
0466 if (r < 0)
0467 goto done;
0468 }
0469
0470 if (dest)
0471 memcpy(dest, fio->output, 1 << v->data_dev_block_bits);
0472 else if (iter) {
0473 fio->output_pos = 0;
0474 r = verity_for_bv_block(v, io, iter, fec_bv_copy);
0475 }
0476
0477 done:
0478 fio->level--;
0479 return r;
0480 }
0481
0482
0483
0484
0485 void verity_fec_finish_io(struct dm_verity_io *io)
0486 {
0487 unsigned n;
0488 struct dm_verity_fec *f = io->v->fec;
0489 struct dm_verity_fec_io *fio = fec_io(io);
0490
0491 if (!verity_fec_is_enabled(io->v))
0492 return;
0493
0494 mempool_free(fio->rs, &f->rs_pool);
0495
0496 fec_for_each_prealloc_buffer(n)
0497 mempool_free(fio->bufs[n], &f->prealloc_pool);
0498
0499 fec_for_each_extra_buffer(fio, n)
0500 mempool_free(fio->bufs[n], &f->extra_pool);
0501
0502 mempool_free(fio->output, &f->output_pool);
0503 }
0504
0505
0506
0507
0508 void verity_fec_init_io(struct dm_verity_io *io)
0509 {
0510 struct dm_verity_fec_io *fio = fec_io(io);
0511
0512 if (!verity_fec_is_enabled(io->v))
0513 return;
0514
0515 fio->rs = NULL;
0516 memset(fio->bufs, 0, sizeof(fio->bufs));
0517 fio->nbufs = 0;
0518 fio->output = NULL;
0519 fio->level = 0;
0520 }
0521
0522
0523
0524
0525 unsigned verity_fec_status_table(struct dm_verity *v, unsigned sz,
0526 char *result, unsigned maxlen)
0527 {
0528 if (!verity_fec_is_enabled(v))
0529 return sz;
0530
0531 DMEMIT(" " DM_VERITY_OPT_FEC_DEV " %s "
0532 DM_VERITY_OPT_FEC_BLOCKS " %llu "
0533 DM_VERITY_OPT_FEC_START " %llu "
0534 DM_VERITY_OPT_FEC_ROOTS " %d",
0535 v->fec->dev->name,
0536 (unsigned long long)v->fec->blocks,
0537 (unsigned long long)v->fec->start,
0538 v->fec->roots);
0539
0540 return sz;
0541 }
0542
0543 void verity_fec_dtr(struct dm_verity *v)
0544 {
0545 struct dm_verity_fec *f = v->fec;
0546
0547 if (!verity_fec_is_enabled(v))
0548 goto out;
0549
0550 mempool_exit(&f->rs_pool);
0551 mempool_exit(&f->prealloc_pool);
0552 mempool_exit(&f->extra_pool);
0553 mempool_exit(&f->output_pool);
0554 kmem_cache_destroy(f->cache);
0555
0556 if (f->data_bufio)
0557 dm_bufio_client_destroy(f->data_bufio);
0558 if (f->bufio)
0559 dm_bufio_client_destroy(f->bufio);
0560
0561 if (f->dev)
0562 dm_put_device(v->ti, f->dev);
0563 out:
0564 kfree(f);
0565 v->fec = NULL;
0566 }
0567
0568 static void *fec_rs_alloc(gfp_t gfp_mask, void *pool_data)
0569 {
0570 struct dm_verity *v = (struct dm_verity *)pool_data;
0571
0572 return init_rs_gfp(8, 0x11d, 0, 1, v->fec->roots, gfp_mask);
0573 }
0574
0575 static void fec_rs_free(void *element, void *pool_data)
0576 {
0577 struct rs_control *rs = (struct rs_control *)element;
0578
0579 if (rs)
0580 free_rs(rs);
0581 }
0582
0583 bool verity_is_fec_opt_arg(const char *arg_name)
0584 {
0585 return (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_DEV) ||
0586 !strcasecmp(arg_name, DM_VERITY_OPT_FEC_BLOCKS) ||
0587 !strcasecmp(arg_name, DM_VERITY_OPT_FEC_START) ||
0588 !strcasecmp(arg_name, DM_VERITY_OPT_FEC_ROOTS));
0589 }
0590
0591 int verity_fec_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
0592 unsigned *argc, const char *arg_name)
0593 {
0594 int r;
0595 struct dm_target *ti = v->ti;
0596 const char *arg_value;
0597 unsigned long long num_ll;
0598 unsigned char num_c;
0599 char dummy;
0600
0601 if (!*argc) {
0602 ti->error = "FEC feature arguments require a value";
0603 return -EINVAL;
0604 }
0605
0606 arg_value = dm_shift_arg(as);
0607 (*argc)--;
0608
0609 if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_DEV)) {
0610 r = dm_get_device(ti, arg_value, FMODE_READ, &v->fec->dev);
0611 if (r) {
0612 ti->error = "FEC device lookup failed";
0613 return r;
0614 }
0615
0616 } else if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_BLOCKS)) {
0617 if (sscanf(arg_value, "%llu%c", &num_ll, &dummy) != 1 ||
0618 ((sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT))
0619 >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll)) {
0620 ti->error = "Invalid " DM_VERITY_OPT_FEC_BLOCKS;
0621 return -EINVAL;
0622 }
0623 v->fec->blocks = num_ll;
0624
0625 } else if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_START)) {
0626 if (sscanf(arg_value, "%llu%c", &num_ll, &dummy) != 1 ||
0627 ((sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) >>
0628 (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll)) {
0629 ti->error = "Invalid " DM_VERITY_OPT_FEC_START;
0630 return -EINVAL;
0631 }
0632 v->fec->start = num_ll;
0633
0634 } else if (!strcasecmp(arg_name, DM_VERITY_OPT_FEC_ROOTS)) {
0635 if (sscanf(arg_value, "%hhu%c", &num_c, &dummy) != 1 || !num_c ||
0636 num_c < (DM_VERITY_FEC_RSM - DM_VERITY_FEC_MAX_RSN) ||
0637 num_c > (DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN)) {
0638 ti->error = "Invalid " DM_VERITY_OPT_FEC_ROOTS;
0639 return -EINVAL;
0640 }
0641 v->fec->roots = num_c;
0642
0643 } else {
0644 ti->error = "Unrecognized verity FEC feature request";
0645 return -EINVAL;
0646 }
0647
0648 return 0;
0649 }
0650
0651
0652
0653
0654 int verity_fec_ctr_alloc(struct dm_verity *v)
0655 {
0656 struct dm_verity_fec *f;
0657
0658 f = kzalloc(sizeof(struct dm_verity_fec), GFP_KERNEL);
0659 if (!f) {
0660 v->ti->error = "Cannot allocate FEC structure";
0661 return -ENOMEM;
0662 }
0663 v->fec = f;
0664
0665 return 0;
0666 }
0667
0668
0669
0670
0671
0672 int verity_fec_ctr(struct dm_verity *v)
0673 {
0674 struct dm_verity_fec *f = v->fec;
0675 struct dm_target *ti = v->ti;
0676 u64 hash_blocks, fec_blocks;
0677 int ret;
0678
0679 if (!verity_fec_is_enabled(v)) {
0680 verity_fec_dtr(v);
0681 return 0;
0682 }
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699 hash_blocks = v->hash_blocks - v->hash_start;
0700
0701
0702
0703
0704
0705 if (v->data_dev_block_bits != v->hash_dev_block_bits) {
0706 ti->error = "Block sizes must match to use FEC";
0707 return -EINVAL;
0708 }
0709
0710 if (!f->roots) {
0711 ti->error = "Missing " DM_VERITY_OPT_FEC_ROOTS;
0712 return -EINVAL;
0713 }
0714 f->rsn = DM_VERITY_FEC_RSM - f->roots;
0715
0716 if (!f->blocks) {
0717 ti->error = "Missing " DM_VERITY_OPT_FEC_BLOCKS;
0718 return -EINVAL;
0719 }
0720
0721 f->rounds = f->blocks;
0722 if (sector_div(f->rounds, f->rsn))
0723 f->rounds++;
0724
0725
0726
0727
0728
0729 if (f->blocks < v->data_blocks + hash_blocks || !f->rounds) {
0730 ti->error = "Invalid " DM_VERITY_OPT_FEC_BLOCKS;
0731 return -EINVAL;
0732 }
0733
0734
0735
0736
0737
0738 f->hash_blocks = f->blocks - v->data_blocks;
0739 if (dm_bufio_get_device_size(v->bufio) < f->hash_blocks) {
0740 ti->error = "Hash device is too small for "
0741 DM_VERITY_OPT_FEC_BLOCKS;
0742 return -E2BIG;
0743 }
0744
0745 if ((f->roots << SECTOR_SHIFT) & ((1 << v->data_dev_block_bits) - 1))
0746 f->io_size = 1 << v->data_dev_block_bits;
0747 else
0748 f->io_size = v->fec->roots << SECTOR_SHIFT;
0749
0750 f->bufio = dm_bufio_client_create(f->dev->bdev,
0751 f->io_size,
0752 1, 0, NULL, NULL, 0);
0753 if (IS_ERR(f->bufio)) {
0754 ti->error = "Cannot initialize FEC bufio client";
0755 return PTR_ERR(f->bufio);
0756 }
0757
0758 dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits - SECTOR_SHIFT));
0759
0760 fec_blocks = div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT);
0761 if (dm_bufio_get_device_size(f->bufio) < fec_blocks) {
0762 ti->error = "FEC device is too small";
0763 return -E2BIG;
0764 }
0765
0766 f->data_bufio = dm_bufio_client_create(v->data_dev->bdev,
0767 1 << v->data_dev_block_bits,
0768 1, 0, NULL, NULL, 0);
0769 if (IS_ERR(f->data_bufio)) {
0770 ti->error = "Cannot initialize FEC data bufio client";
0771 return PTR_ERR(f->data_bufio);
0772 }
0773
0774 if (dm_bufio_get_device_size(f->data_bufio) < v->data_blocks) {
0775 ti->error = "Data device is too small";
0776 return -E2BIG;
0777 }
0778
0779
0780 ret = mempool_init(&f->rs_pool, num_online_cpus(), fec_rs_alloc,
0781 fec_rs_free, (void *) v);
0782 if (ret) {
0783 ti->error = "Cannot allocate RS pool";
0784 return ret;
0785 }
0786
0787 f->cache = kmem_cache_create("dm_verity_fec_buffers",
0788 f->rsn << DM_VERITY_FEC_BUF_RS_BITS,
0789 0, 0, NULL);
0790 if (!f->cache) {
0791 ti->error = "Cannot create FEC buffer cache";
0792 return -ENOMEM;
0793 }
0794
0795
0796 ret = mempool_init_slab_pool(&f->prealloc_pool, num_online_cpus() *
0797 DM_VERITY_FEC_BUF_PREALLOC,
0798 f->cache);
0799 if (ret) {
0800 ti->error = "Cannot allocate FEC buffer prealloc pool";
0801 return ret;
0802 }
0803
0804 ret = mempool_init_slab_pool(&f->extra_pool, 0, f->cache);
0805 if (ret) {
0806 ti->error = "Cannot allocate FEC buffer extra pool";
0807 return ret;
0808 }
0809
0810
0811 ret = mempool_init_kmalloc_pool(&f->output_pool, num_online_cpus(),
0812 1 << v->data_dev_block_bits);
0813 if (ret) {
0814 ti->error = "Cannot allocate FEC output pool";
0815 return ret;
0816 }
0817
0818
0819 ti->per_io_data_size += sizeof(struct dm_verity_fec_io);
0820
0821 return 0;
0822 }