The addition of percpu.h to the list of includes in random.h revealed some circular dependencies on arm64 and possibly other platforms. This include was added solely for the pseudo-random definitions, which have nothing to do with the rest of the definitions in this file but are still there for legacy reasons. This patch moves the pseudo-random parts to linux/prandom.h and the percpu.h include with it, which is now guarded by _LINUX_PRANDOM_H and protected against recursive inclusion. A further cleanup step would be to remove this from <linux/random.h> entirely, and make people who use the prandom infrastructure include just the new header file. That's a bit of a churn patch, but grepping for "prandom_" and "next_pseudo_random32" "struct rnd_state" should catch most users. But it turns out that that nice cleanup step is fairly painful, because a _lot_ of code currently seems to depend on the implicit include of <linux/random.h>, which can currently come in a lot of ways, including such fairly core headfers as <linux/net.h>. So the "nice cleanup" part may or may never happen.
Showing the changes to include/linux (2 of 2 files). Show all
Unified · Split
| @@ -0,0 +1,78 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +/* | |
| 3 | + * include/linux/prandom.h | |
| 4 | + * | |
| 5 | + * Include file for the fast pseudo-random 32-bit | |
| 6 | + * generation. | |
| 7 | + */ | |
| 8 | +#ifndef _LINUX_PRANDOM_H | |
| 9 | +#define _LINUX_PRANDOM_H | |
| 10 | + | |
| 11 | +#include <linux/types.h> | |
| 12 | +#include <linux/percpu.h> | |
| 13 | + | |
| 14 | +u32 prandom_u32(void); | |
| 15 | +void prandom_bytes(void *buf, size_t nbytes); | |
| 16 | +void prandom_seed(u32 seed); | |
| 17 | +void prandom_reseed_late(void); | |
| 18 | + | |
| 19 | +struct rnd_state { | |
| 20 | + __u32 s1, s2, s3, s4; | |
| 21 | +}; | |
| 22 | + | |
| 23 | +DECLARE_PER_CPU(struct rnd_state, net_rand_state); | |
| 24 | + | |
| 25 | +u32 prandom_u32_state(struct rnd_state *state); | |
| 26 | +void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); | |
| 27 | +void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); | |
| 28 | + | |
| 29 | +#define prandom_init_once(pcpu_state) \ | |
| 30 | + DO_ONCE(prandom_seed_full_state, (pcpu_state)) | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) | |
| 34 | + * @ep_ro: right open interval endpoint | |
| 35 | + * | |
| 36 | + * Returns a pseudo-random number that is in interval [0, ep_ro). Note | |
| 37 | + * that the result depends on PRNG being well distributed in [0, ~0U] | |
| 38 | + * u32 space. Here we use maximally equidistributed combined Tausworthe | |
| 39 | + * generator, that is, prandom_u32(). This is useful when requesting a | |
| 40 | + * random index of an array containing ep_ro elements, for example. | |
| 41 | + * | |
| 42 | + * Returns: pseudo-random number in interval [0, ep_ro) | |
| 43 | + */ | |
| 44 | +static inline u32 prandom_u32_max(u32 ep_ro) | |
| 45 | +{ | |
| 46 | + return (u32)(((u64) prandom_u32() * ep_ro) >> 32); | |
| 47 | +} | |
| 48 | + | |
| 49 | +/* | |
| 50 | + * Handle minimum values for seeds | |
| 51 | + */ | |
| 52 | +static inline u32 __seed(u32 x, u32 m) | |
| 53 | +{ | |
| 54 | + return (x < m) ? x + m : x; | |
| 55 | +} | |
| 56 | + | |
| 57 | +/** | |
| 58 | + * prandom_seed_state - set seed for prandom_u32_state(). | |
| 59 | + * @state: pointer to state structure to receive the seed. | |
| 60 | + * @seed: arbitrary 64-bit value to use as a seed. | |
| 61 | + */ | |
| 62 | +static inline void prandom_seed_state(struct rnd_state *state, u64 seed) | |
| 63 | +{ | |
| 64 | + u32 i = (seed >> 32) ^ (seed << 10) ^ seed; | |
| 65 | + | |
| 66 | + state->s1 = __seed(i, 2U); | |
| 67 | + state->s2 = __seed(i, 8U); | |
| 68 | + state->s3 = __seed(i, 16U); | |
| 69 | + state->s4 = __seed(i, 128U); | |
| 70 | +} | |
| 71 | + | |
| 72 | +/* Pseudo random number generator from numerical recipes. */ | |
| 73 | +static inline u32 next_pseudo_random32(u32 seed) | |
| 74 | +{ | |
| 75 | + return seed * 1664525 + 1013904223; | |
| 76 | +} | |
| 77 | + | |
| 78 | +#endif | |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/kernel.h> |
| 12 | 12 | #include <linux/list.h> |
| 13 | 13 | #include <linux/once.h> |
| 14 | −#include <asm/percpu.h> | |
| 15 | 14 | |
| 16 | 15 | #include <uapi/linux/random.h> |
| 17 | 16 | |
| @@ -111,63 +110,12 @@ declare_get_random_var_wait(long) · 93 unmodified lines | ||
| 111 | 110 | |
| 112 | 111 | unsigned long randomize_page(unsigned long start, unsigned long range); |
| 113 | 112 | |
| 114 | −u32 prandom_u32(void); | |
| 115 | −void prandom_bytes(void *buf, size_t nbytes); | |
| 116 | −void prandom_seed(u32 seed); | |
| 117 | −void prandom_reseed_late(void); | |
| 118 | − | |
| 119 | −struct rnd_state { | |
| 120 | − __u32 s1, s2, s3, s4; | |
| 121 | −}; | |
| 122 | − | |
| 123 | −DECLARE_PER_CPU(struct rnd_state, net_rand_state); | |
| 124 | − | |
| 125 | −u32 prandom_u32_state(struct rnd_state *state); | |
| 126 | −void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); | |
| 127 | −void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); | |
| 128 | − | |
| 129 | −#define prandom_init_once(pcpu_state) \ | |
| 130 | − DO_ONCE(prandom_seed_full_state, (pcpu_state)) | |
| 131 | − | |
| 132 | −/** | |
| 133 | − * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) | |
| 134 | − * @ep_ro: right open interval endpoint | |
| 135 | − * | |
| 136 | − * Returns a pseudo-random number that is in interval [0, ep_ro). Note | |
| 137 | − * that the result depends on PRNG being well distributed in [0, ~0U] | |
| 138 | − * u32 space. Here we use maximally equidistributed combined Tausworthe | |
| 139 | − * generator, that is, prandom_u32(). This is useful when requesting a | |
| 140 | − * random index of an array containing ep_ro elements, for example. | |
| 141 | − * | |
| 142 | − * Returns: pseudo-random number in interval [0, ep_ro) | |
| 143 | − */ | |
| 144 | −static inline u32 prandom_u32_max(u32 ep_ro) | |
| 145 | −{ | |
| 146 | − return (u32)(((u64) prandom_u32() * ep_ro) >> 32); | |
| 147 | −} | |
| 148 | − | |
| 149 | 113 | /* |
| 150 | − * Handle minimum values for seeds | |
| 151 | − */ | |
| 152 | −static inline u32 __seed(u32 x, u32 m) | |
| 153 | −{ | |
| 154 | − return (x < m) ? x + m : x; | |
| 155 | −} | |
| 156 | − | |
| 157 | −/** | |
| 158 | − * prandom_seed_state - set seed for prandom_u32_state(). | |
| 159 | − * @state: pointer to state structure to receive the seed. | |
| 160 | − * @seed: arbitrary 64-bit value to use as a seed. | |
| 114 | + * This is designed to be standalone for just prandom | |
| 115 | + * users, but for now we include it from <linux/random.h> | |
| 116 | + * for legacy reasons. | |
| 161 | 117 | */ |
| 162 | −static inline void prandom_seed_state(struct rnd_state *state, u64 seed) | |
| 163 | −{ | |
| 164 | − u32 i = (seed >> 32) ^ (seed << 10) ^ seed; | |
| 165 | − | |
| 166 | − state->s1 = __seed(i, 2U); | |
| 167 | − state->s2 = __seed(i, 8U); | |
| 168 | − state->s3 = __seed(i, 16U); | |
| 169 | − state->s4 = __seed(i, 128U); | |
| 170 | −} | |
| 118 | +#include <linux/prandom.h> | |
| 171 | 119 | |
| 172 | 120 | #ifdef CONFIG_ARCH_RANDOM |
| 173 | 121 | # include <asm/archrandom.h> |
| @@ -210,10 +158,4 @@ static inline bool __init arch_get_random_long_early(unsigned long *v) · 36 unmodified lines | ||
| 210 | 158 | } |
| 211 | 159 | #endif |
| 212 | 160 | |
| 213 | −/* Pseudo random number generator from numerical recipes. */ | |
| 214 | −static inline u32 next_pseudo_random32(u32 seed) | |
| 215 | −{ | |
| 216 | − return seed * 1664525 + 1013904223; | |
| 217 | −} | |
| 218 | − | |
| 219 | 161 | #endif /* _LINUX_RANDOM_H */ |