aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-04-22 12:23:46 -0400
committerKees Cook <keescook@chromium.org>2018-04-24 22:50:04 -0400
commit83a530e1610ab996e59c0941db6cc72f763dddbd (patch)
treec5abcba7d5b8213ec3ddc39cb7508d80aab08469
parent6d08b06e67cd117f6992c46611dfb4ce267cd71e (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.h28
-rw-r--r--lib/reed_solomon/reed_solomon.c43
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 */
80struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, 82struct 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 */
98static 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
82struct rs_control *init_rs_non_canonical(int symsize, int (*func)(int), 104struct 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 */
86void free_rs(struct rs_control *rs); 108void 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 */
66static struct rs_control *rs_init(int symsize, int gfpoly, int (*gffunc)(int), 67static 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}
185EXPORT_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 */
199static struct rs_control *init_rs_internal(int symsize, int gfpoly, 202static 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 */
260struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, 264struct 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}
269EXPORT_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,
279struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), 284struct 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}
290EXPORT_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,
374EXPORT_SYMBOL_GPL(decode_rs16); 381EXPORT_SYMBOL_GPL(decode_rs16);
375#endif 382#endif
376 383
377EXPORT_SYMBOL_GPL(init_rs);
378EXPORT_SYMBOL_GPL(init_rs_non_canonical);
379EXPORT_SYMBOL_GPL(free_rs);
380
381MODULE_LICENSE("GPL"); 384MODULE_LICENSE("GPL");
382MODULE_DESCRIPTION("Reed Solomon encoder/decoder"); 385MODULE_DESCRIPTION("Reed Solomon encoder/decoder");
383MODULE_AUTHOR("Phil Karn, Thomas Gleixner"); 386MODULE_AUTHOR("Phil Karn, Thomas Gleixner");