Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

random32: move the pseudo-random 32-bit definitions to prandom.h

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.

Fixes: 1c9df907da83 ("random: fix circular include dependency on arm64 after addition of percpu.h")
Tested-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+82 -62
+78
include/linux/prandom.h
··· 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
+4 -62
include/linux/random.h
··· 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 ··· 110 111 111 112 unsigned long randomize_page(unsigned long start, unsigned long range); 112 113 113 - u32 prandom_u32(void); 114 - void prandom_bytes(void *buf, size_t nbytes); 115 - void prandom_seed(u32 seed); 116 - void prandom_reseed_late(void); 117 - 118 - struct rnd_state { 119 - __u32 s1, s2, s3, s4; 120 - }; 121 - 122 - DECLARE_PER_CPU(struct rnd_state, net_rand_state); 123 - 124 - u32 prandom_u32_state(struct rnd_state *state); 125 - void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); 126 - void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); 127 - 128 - #define prandom_init_once(pcpu_state) \ 129 - DO_ONCE(prandom_seed_full_state, (pcpu_state)) 130 - 131 - /** 132 - * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) 133 - * @ep_ro: right open interval endpoint 134 - * 135 - * Returns a pseudo-random number that is in interval [0, ep_ro). Note 136 - * that the result depends on PRNG being well distributed in [0, ~0U] 137 - * u32 space. Here we use maximally equidistributed combined Tausworthe 138 - * generator, that is, prandom_u32(). This is useful when requesting a 139 - * random index of an array containing ep_ro elements, for example. 140 - * 141 - * Returns: pseudo-random number in interval [0, ep_ro) 142 - */ 143 - static inline u32 prandom_u32_max(u32 ep_ro) 144 - { 145 - return (u32)(((u64) prandom_u32() * ep_ro) >> 32); 146 - } 147 - 148 114 /* 149 - * Handle minimum values for seeds 115 + * This is designed to be standalone for just prandom 116 + * users, but for now we include it from <linux/random.h> 117 + * for legacy reasons. 150 118 */ 151 - static inline u32 __seed(u32 x, u32 m) 152 - { 153 - return (x < m) ? x + m : x; 154 - } 155 - 156 - /** 157 - * prandom_seed_state - set seed for prandom_u32_state(). 158 - * @state: pointer to state structure to receive the seed. 159 - * @seed: arbitrary 64-bit value to use as a seed. 160 - */ 161 - static inline void prandom_seed_state(struct rnd_state *state, u64 seed) 162 - { 163 - u32 i = (seed >> 32) ^ (seed << 10) ^ seed; 164 - 165 - state->s1 = __seed(i, 2U); 166 - state->s2 = __seed(i, 8U); 167 - state->s3 = __seed(i, 16U); 168 - state->s4 = __seed(i, 128U); 169 - } 119 + #include <linux/prandom.h> 170 120 171 121 #ifdef CONFIG_ARCH_RANDOM 172 122 # include <asm/archrandom.h> ··· 157 209 return arch_get_random_long(v); 158 210 } 159 211 #endif 160 - 161 - /* Pseudo random number generator from numerical recipes. */ 162 - static inline u32 next_pseudo_random32(u32 seed) 163 - { 164 - return seed * 1664525 + 1013904223; 165 - } 166 212 167 213 #endif /* _LINUX_RANDOM_H */