1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Copyright (C) 2015 Google, Inc. 4 * 5 * Author: Sami Tolvanen <samitolvanen@google.com> 6 */ 7 8 #ifndef DM_VERITY_FEC_H 9 #define DM_VERITY_FEC_H 10 11 #include "dm-verity.h" 12 #include <linux/rslib.h> 13 14 /* Reed-Solomon(M, N) parameters */ 15 #define DM_VERITY_FEC_RSM 255 16 #define DM_VERITY_FEC_MAX_RSN 253 17 #define DM_VERITY_FEC_MIN_RSN 231 /* ~10% space overhead */ 18 19 /* buffers for deinterleaving and decoding */ 20 #define DM_VERITY_FEC_BUF_RS_BITS 4 /* 1 << RS blocks per buffer */ 21 22 #define DM_VERITY_OPT_FEC_DEV "use_fec_from_device" 23 #define DM_VERITY_OPT_FEC_BLOCKS "fec_blocks" 24 #define DM_VERITY_OPT_FEC_START "fec_start" 25 #define DM_VERITY_OPT_FEC_ROOTS "fec_roots" 26 27 /* configuration */ 28 struct dm_verity_fec { 29 struct dm_dev *dev; /* parity data device */ 30 struct dm_bufio_client *data_bufio; /* for data dev access */ 31 struct dm_bufio_client *bufio; /* for parity data access */ 32 size_t io_size; /* IO size for roots */ 33 sector_t start; /* parity data start in blocks */ 34 sector_t blocks; /* number of blocks covered */ 35 sector_t rounds; /* number of interleaving rounds */ 36 sector_t hash_blocks; /* blocks covered after v->hash_start */ 37 unsigned char roots; /* number of parity bytes, M-N of RS(M, N) */ 38 unsigned char rsn; /* N of RS(M, N) */ 39 mempool_t fio_pool; /* mempool for dm_verity_fec_io */ 40 mempool_t rs_pool; /* mempool for fio->rs */ 41 mempool_t prealloc_pool; /* mempool for preallocated buffers */ 42 mempool_t output_pool; /* mempool for output */ 43 struct kmem_cache *cache; /* cache for buffers */ 44 atomic64_t corrected; /* corrected errors */ 45 }; 46 47 /* per-bio data */ 48 struct dm_verity_fec_io { 49 struct rs_control *rs; /* Reed-Solomon state */ 50 int erasures[DM_VERITY_FEC_MAX_RSN]; /* erasures for decode_rs8 */ 51 u8 *output; /* buffer for corrected output */ 52 unsigned int level; /* recursion level */ 53 unsigned int nbufs; /* number of buffers allocated */ 54 /* 55 * Buffers for deinterleaving RS blocks. Each buffer has space for 56 * the data bytes of (1 << DM_VERITY_FEC_BUF_RS_BITS) RS blocks. The 57 * array length is fec_max_nbufs(v), and we try to allocate that many 58 * buffers. However, in low-memory situations we may be unable to 59 * allocate all buffers. 'nbufs' holds the number actually allocated. 60 */ 61 u8 *bufs[]; 62 }; 63 64 #ifdef CONFIG_DM_VERITY_FEC 65 66 /* each feature parameter requires a value */ 67 #define DM_VERITY_OPTS_FEC 8 68 69 /* Returns true if forward error correction is enabled. */ 70 static inline bool verity_fec_is_enabled(struct dm_verity *v) 71 { 72 return v->fec && v->fec->dev; 73 } 74 75 extern int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io, 76 enum verity_block_type type, const u8 *want_digest, 77 sector_t block, u8 *dest); 78 79 extern unsigned int verity_fec_status_table(struct dm_verity *v, unsigned int sz, 80 char *result, unsigned int maxlen); 81 82 extern void __verity_fec_finish_io(struct dm_verity_io *io); 83 static inline void verity_fec_finish_io(struct dm_verity_io *io) 84 { 85 if (unlikely(io->fec_io)) 86 __verity_fec_finish_io(io); 87 } 88 89 static inline void verity_fec_init_io(struct dm_verity_io *io) 90 { 91 io->fec_io = NULL; 92 } 93 94 extern bool verity_is_fec_opt_arg(const char *arg_name); 95 extern int verity_fec_parse_opt_args(struct dm_arg_set *as, 96 struct dm_verity *v, unsigned int *argc, 97 const char *arg_name); 98 99 extern void verity_fec_dtr(struct dm_verity *v); 100 101 extern int verity_fec_ctr_alloc(struct dm_verity *v); 102 extern int verity_fec_ctr(struct dm_verity *v); 103 104 #else /* !CONFIG_DM_VERITY_FEC */ 105 106 #define DM_VERITY_OPTS_FEC 0 107 108 static inline bool verity_fec_is_enabled(struct dm_verity *v) 109 { 110 return false; 111 } 112 113 static inline int verity_fec_decode(struct dm_verity *v, 114 struct dm_verity_io *io, 115 enum verity_block_type type, 116 const u8 *want_digest, 117 sector_t block, u8 *dest) 118 { 119 return -EOPNOTSUPP; 120 } 121 122 static inline unsigned int verity_fec_status_table(struct dm_verity *v, 123 unsigned int sz, char *result, 124 unsigned int maxlen) 125 { 126 return sz; 127 } 128 129 static inline void verity_fec_finish_io(struct dm_verity_io *io) 130 { 131 } 132 133 static inline void verity_fec_init_io(struct dm_verity_io *io) 134 { 135 } 136 137 static inline bool verity_is_fec_opt_arg(const char *arg_name) 138 { 139 return false; 140 } 141 142 static inline int verity_fec_parse_opt_args(struct dm_arg_set *as, 143 struct dm_verity *v, 144 unsigned int *argc, 145 const char *arg_name) 146 { 147 return -EINVAL; 148 } 149 150 static inline void verity_fec_dtr(struct dm_verity *v) 151 { 152 } 153 154 static inline int verity_fec_ctr_alloc(struct dm_verity *v) 155 { 156 return 0; 157 } 158 159 static inline int verity_fec_ctr(struct dm_verity *v) 160 { 161 return 0; 162 } 163 164 #endif /* CONFIG_DM_VERITY_FEC */ 165 166 #endif /* DM_VERITY_FEC_H */ 167