diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2018-04-22 12:23:46 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2018-04-24 22:50:04 -0400 |
commit | 83a530e1610ab996e59c0941db6cc72f763dddbd (patch) | |
tree | c5abcba7d5b8213ec3ddc39cb7508d80aab08469 | |
parent | 6d08b06e67cd117f6992c46611dfb4ce267cd71e (diff) |
rslib: Add GFP aware init function
The rslib usage in dm/verity_fec is broken because init_rs() can nest in
GFP_NOIO mempool allocations as init_rs() is invoked from the mempool alloc
callback.
Provide a variant which takes gfp_t flags as argument.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Mike Snitzer <snitzer@redhat.com>
Cc: Alasdair Kergon <agk@redhat.com>
Cc: Neil Brown <neilb@suse.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r-- | include/linux/rslib.h | 28 | ||||
-rw-r--r-- | lib/reed_solomon/reed_solomon.c | 43 |
2 files changed, 48 insertions, 23 deletions
diff --git a/include/linux/rslib.h b/include/linux/rslib.h index 746580c1939c..2aae7ef987eb 100644 --- a/include/linux/rslib.h +++ b/include/linux/rslib.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #define _RSLIB_H_ | 20 | #define _RSLIB_H_ |
21 | 21 | ||
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/types.h> /* for gfp_t */ | ||
24 | #include <linux/gfp.h> /* for GFP_KERNEL */ | ||
23 | 25 | ||
24 | /** | 26 | /** |
25 | * struct rs_control - rs control structure | 27 | * struct rs_control - rs control structure |
@@ -77,10 +79,30 @@ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len, | |||
77 | #endif | 79 | #endif |
78 | 80 | ||
79 | /* Create or get a matching rs control structure */ | 81 | /* Create or get a matching rs control structure */ |
80 | struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, | 82 | struct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim, |
81 | int nroots); | 83 | int nroots, gfp_t gfp); |
84 | |||
85 | /** | ||
86 | * init_rs - Create a RS control struct and initialize it | ||
87 | * @symsize: the symbol size (number of bits) | ||
88 | * @gfpoly: the extended Galois field generator polynomial coefficients, | ||
89 | * with the 0th coefficient in the low order bit. The polynomial | ||
90 | * must be primitive; | ||
91 | * @fcr: the first consecutive root of the rs code generator polynomial | ||
92 | * in index form | ||
93 | * @prim: primitive element to generate polynomial roots | ||
94 | * @nroots: RS code generator polynomial degree (number of roots) | ||
95 | * | ||
96 | * Allocations use GFP_KERNEL. | ||
97 | */ | ||
98 | static inline struct rs_control *init_rs(int symsize, int gfpoly, int fcr, | ||
99 | int prim, int nroots) | ||
100 | { | ||
101 | return init_rs_gfp(symsize, gfpoly, fcr, prim, nroots, GFP_KERNEL); | ||
102 | } | ||
103 | |||
82 | struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int), | 104 | struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int), |
83 | int fcr, int prim, int nroots); | 105 | int fcr, int prim, int nroots); |
84 | 106 | ||
85 | /* Release a rs control structure */ | 107 | /* Release a rs control structure */ |
86 | void free_rs(struct rs_control *rs); | 108 | void free_rs(struct rs_control *rs); |
diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index 06d04cfa9339..f8ae1f7b3558 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c | |||
@@ -59,19 +59,20 @@ static DEFINE_MUTEX(rslistlock); | |||
59 | * @fcr: first root of RS code generator polynomial, index form | 59 | * @fcr: first root of RS code generator polynomial, index form |
60 | * @prim: primitive element to generate polynomial roots | 60 | * @prim: primitive element to generate polynomial roots |
61 | * @nroots: RS code generator polynomial degree (number of roots) | 61 | * @nroots: RS code generator polynomial degree (number of roots) |
62 | * @gfp: GFP_ flags for allocations | ||
62 | * | 63 | * |
63 | * Allocate a control structure and the polynom arrays for faster | 64 | * Allocate a control structure and the polynom arrays for faster |
64 | * en/decoding. Fill the arrays according to the given parameters. | 65 | * en/decoding. Fill the arrays according to the given parameters. |
65 | */ | 66 | */ |
66 | static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int), | 67 | static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int), |
67 | int fcr, int prim, int nroots) | 68 | int fcr, int prim, int nroots, gfp_t gfp) |
68 | { | 69 | { |
69 | struct rs_control *rs; | 70 | struct rs_control *rs; |
70 | int i, j, sr, root, iprim; | 71 | int i, j, sr, root, iprim; |
71 | 72 | ||
72 | /* Allocate the control structure */ | 73 | /* Allocate the control structure */ |
73 | rs = kmalloc(sizeof (struct rs_control), GFP_KERNEL); | 74 | rs = kmalloc(sizeof(*rs), gfp); |
74 | if (rs == NULL) | 75 | if (!rs) |
75 | return NULL; | 76 | return NULL; |
76 | 77 | ||
77 | INIT_LIST_HEAD(&rs->list); | 78 | INIT_LIST_HEAD(&rs->list); |
@@ -85,15 +86,15 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int), | |||
85 | rs->gffunc = gffunc; | 86 | rs->gffunc = gffunc; |
86 | 87 | ||
87 | /* Allocate the arrays */ | 88 | /* Allocate the arrays */ |
88 | rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); | 89 | rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), gfp); |
89 | if (rs->alpha_to == NULL) | 90 | if (rs->alpha_to == NULL) |
90 | goto errrs; | 91 | goto errrs; |
91 | 92 | ||
92 | rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), GFP_KERNEL); | 93 | rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), gfp); |
93 | if (rs->index_of == NULL) | 94 | if (rs->index_of == NULL) |
94 | goto erralp; | 95 | goto erralp; |
95 | 96 | ||
96 | rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), GFP_KERNEL); | 97 | rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), gfp); |
97 | if(rs->genpoly == NULL) | 98 | if(rs->genpoly == NULL) |
98 | goto erridx; | 99 | goto erridx; |
99 | 100 | ||
@@ -181,6 +182,7 @@ void free_rs(struct rs_control *rs) | |||
181 | } | 182 | } |
182 | mutex_unlock(&rslistlock); | 183 | mutex_unlock(&rslistlock); |
183 | } | 184 | } |
185 | EXPORT_SYMBOL_GPL(free_rs); | ||
184 | 186 | ||
185 | /** | 187 | /** |
186 | * init_rs_internal - Find a matching or allocate a new rs control structure | 188 | * init_rs_internal - Find a matching or allocate a new rs control structure |
@@ -195,13 +197,14 @@ void free_rs(struct rs_control *rs) | |||
195 | * in index form | 197 | * in index form |
196 | * @prim: primitive element to generate polynomial roots | 198 | * @prim: primitive element to generate polynomial roots |
197 | * @nroots: RS code generator polynomial degree (number of roots) | 199 | * @nroots: RS code generator polynomial degree (number of roots) |
200 | * @gfp: GFP_ flags for allocations | ||
198 | */ | 201 | */ |
199 | static struct rs_control *init_rs_internal(int symsize, int gfpoly, | 202 | static struct rs_control *init_rs_internal(int symsize, int gfpoly, |
200 | int (*gffunc)(int), int fcr, | 203 | int (*gffunc)(int), int fcr, |
201 | int prim, int nroots) | 204 | int prim, int nroots, gfp_t gfp) |
202 | { | 205 | { |
203 | struct list_head *tmp; | 206 | struct list_head *tmp; |
204 | struct rs_control *rs; | 207 | struct rs_control *rs; |
205 | 208 | ||
206 | /* Sanity checks */ | 209 | /* Sanity checks */ |
207 | if (symsize < 1) | 210 | if (symsize < 1) |
@@ -236,7 +239,7 @@ static struct rs_control *init_rs_internal(int symsize, int gfpoly, | |||
236 | } | 239 | } |
237 | 240 | ||
238 | /* Create a new one */ | 241 | /* Create a new one */ |
239 | rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots); | 242 | rs = rs_init(symsize, gfpoly, gffunc, fcr, prim, nroots, gfp); |
240 | if (rs) { | 243 | if (rs) { |
241 | rs->users = 1; | 244 | rs->users = 1; |
242 | list_add(&rs->list, &rslist); | 245 | list_add(&rs->list, &rslist); |
@@ -247,7 +250,7 @@ out: | |||
247 | } | 250 | } |
248 | 251 | ||
249 | /** | 252 | /** |
250 | * init_rs - Find a matching or allocate a new rs control structure | 253 | * init_rs_gfp - Find a matching or allocate a new rs control structure |
251 | * @symsize: the symbol size (number of bits) | 254 | * @symsize: the symbol size (number of bits) |
252 | * @gfpoly: the extended Galois field generator polynomial coefficients, | 255 | * @gfpoly: the extended Galois field generator polynomial coefficients, |
253 | * with the 0th coefficient in the low order bit. The polynomial | 256 | * with the 0th coefficient in the low order bit. The polynomial |
@@ -256,12 +259,14 @@ out: | |||
256 | * in index form | 259 | * in index form |
257 | * @prim: primitive element to generate polynomial roots | 260 | * @prim: primitive element to generate polynomial roots |
258 | * @nroots: RS code generator polynomial degree (number of roots) | 261 | * @nroots: RS code generator polynomial degree (number of roots) |
262 | * @gfp: GFP_ flags for allocations | ||
259 | */ | 263 | */ |
260 | struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, | 264 | struct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim, |
261 | int nroots) | 265 | int nroots, gfp_t gfp) |
262 | { | 266 | { |
263 | return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots); | 267 | return init_rs_internal(symsize, gfpoly, NULL, fcr, prim, nroots, gfp); |
264 | } | 268 | } |
269 | EXPORT_SYMBOL_GPL(init_rs_gfp); | ||
265 | 270 | ||
266 | /** | 271 | /** |
267 | * init_rs_non_canonical - Find a matching or allocate a new rs control | 272 | * init_rs_non_canonical - Find a matching or allocate a new rs control |
@@ -279,8 +284,10 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, | |||
279 | struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), | 284 | struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), |
280 | int fcr, int prim, int nroots) | 285 | int fcr, int prim, int nroots) |
281 | { | 286 | { |
282 | return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots); | 287 | return init_rs_internal(symsize, 0, gffunc, fcr, prim, nroots, |
288 | GFP_KERNEL); | ||
283 | } | 289 | } |
290 | EXPORT_SYMBOL_GPL(init_rs_non_canonical); | ||
284 | 291 | ||
285 | #ifdef CONFIG_REED_SOLOMON_ENC8 | 292 | #ifdef CONFIG_REED_SOLOMON_ENC8 |
286 | /** | 293 | /** |
@@ -374,10 +381,6 @@ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len, | |||
374 | EXPORT_SYMBOL_GPL(decode_rs16); | 381 | EXPORT_SYMBOL_GPL(decode_rs16); |
375 | #endif | 382 | #endif |
376 | 383 | ||
377 | EXPORT_SYMBOL_GPL(init_rs); | ||
378 | EXPORT_SYMBOL_GPL(init_rs_non_canonical); | ||
379 | EXPORT_SYMBOL_GPL(free_rs); | ||
380 | |||
381 | MODULE_LICENSE("GPL"); | 384 | MODULE_LICENSE("GPL"); |
382 | MODULE_DESCRIPTION("Reed Solomon encoder/decoder"); | 385 | MODULE_DESCRIPTION("Reed Solomon encoder/decoder"); |
383 | MODULE_AUTHOR("Phil Karn, Thomas Gleixner"); | 386 | MODULE_AUTHOR("Phil Karn, Thomas Gleixner"); |