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 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/list.h> | 12 | #include <linux/list.h> |
| 13 | #include <linux/once.h> | 13 | #include <linux/once.h> |
| 14 | #include <asm/percpu.h> | ||
| 15 | 14 | ||
| 16 | #include <uapi/linux/random.h> | 15 | #include <uapi/linux/random.h> |
| 17 | 16 | ||
| @@ -111,63 +110,12 @@ declare_get_random_var_wait(long) · 93 unmodified lines | |||
| 111 | 110 | ||
| 112 | unsigned long randomize_page(unsigned long start, unsigned long range); | 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 | 114 | * This is designed to be standalone for just prandom |
| 151 | */ | 115 | * users, but for now we include it from <linux/random.h> |
| 152 | static inline u32 __seed(u32 x, u32 m) | 116 | * for legacy reasons. |
| 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. | ||
| 161 | */ | 117 | */ |
| 162 | static inline void prandom_seed_state(struct rnd_state *state, u64 seed) | 118 | #include <linux/prandom.h> |
| 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 | } | ||
| 171 | 119 | ||
| 172 | #ifdef CONFIG_ARCH_RANDOM | 120 | #ifdef CONFIG_ARCH_RANDOM |
| 173 | # include <asm/archrandom.h> | 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 | #endif | 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 | #endif /* _LINUX_RANDOM_H */ | 161 | #endif /* _LINUX_RANDOM_H */ |