diff options
author | Alexander Motin <[email protected]> | 2021-06-22 19:35:23 -0400 |
---|---|---|
committer | Tony Hutter <[email protected]> | 2021-09-14 12:10:17 -0700 |
commit | f3969ea78b5f54935474d49455cf9c4d6a1e107a (patch) | |
tree | 38dbfbee2cd0bbd24bbc642e2023d3f20bd82b6f /include | |
parent | 6fe6192796f6835163523db94130fb842022f6cf (diff) |
Optimize small random numbers generation
In all places except two spa_get_random() is used for small values,
and the consumers do not require well seeded high quality values.
Switch those two exceptions directly to random_get_pseudo_bytes()
and optimize spa_get_random(), renaming it to random_in_range(),
since it is not related to SPA or ZFS in general.
On FreeBSD directly map random_in_range() to new prng32_bounded() KPI
added in FreeBSD 13. On Linux and in user-space just reduce the type
used to uint32_t to avoid more expensive 64bit division.
Reviewed-by: Ryan Moeller <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Alexander Motin <[email protected]>
Sponsored-By: iXsystems, Inc.
Closes #12183
Diffstat (limited to 'include')
-rw-r--r-- | include/os/freebsd/spl/sys/random.h | 22 | ||||
-rw-r--r-- | include/os/linux/spl/sys/random.h | 15 | ||||
-rw-r--r-- | include/sys/spa.h | 1 | ||||
-rw-r--r-- | include/sys/zfs_context.h | 15 |
4 files changed, 52 insertions, 1 deletions
diff --git a/include/os/freebsd/spl/sys/random.h b/include/os/freebsd/spl/sys/random.h index b3c9115f5..746275e53 100644 --- a/include/os/freebsd/spl/sys/random.h +++ b/include/os/freebsd/spl/sys/random.h @@ -30,6 +30,9 @@ #define _OPENSOLARIS_SYS_RANDOM_H_ #include_next <sys/random.h> +#if __FreeBSD_version >= 1300108 +#include <sys/prng.h> +#endif static inline int random_get_bytes(uint8_t *p, size_t s) @@ -45,4 +48,23 @@ random_get_pseudo_bytes(uint8_t *p, size_t s) return (0); } +static inline uint32_t +random_in_range(uint32_t range) +{ +#if __FreeBSD_version >= 1300108 + return (prng32_bounded(range)); +#else + uint32_t r; + + ASSERT(range != 0); + + if (range == 1) + return (0); + + (void) random_get_pseudo_bytes((void *)&r, sizeof (r)); + + return (r % range); +#endif +} + #endif /* !_OPENSOLARIS_SYS_RANDOM_H_ */ diff --git a/include/os/linux/spl/sys/random.h b/include/os/linux/spl/sys/random.h index 1b8cb60d0..2c446e155 100644 --- a/include/os/linux/spl/sys/random.h +++ b/include/os/linux/spl/sys/random.h @@ -36,4 +36,19 @@ random_get_bytes(uint8_t *ptr, size_t len) extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len); +static __inline__ uint32_t +random_in_range(uint32_t range) +{ + uint32_t r; + + ASSERT(range != 0); + + if (range == 1) + return (0); + + (void) random_get_pseudo_bytes((void *)&r, sizeof (r)); + + return (r % range); +} + #endif /* _SPL_RANDOM_H */ diff --git a/include/sys/spa.h b/include/sys/spa.h index 9dd47a1eb..532926e12 100644 --- a/include/sys/spa.h +++ b/include/sys/spa.h @@ -1086,7 +1086,6 @@ extern spa_t *spa_by_guid(uint64_t pool_guid, uint64_t device_guid); extern boolean_t spa_guid_exists(uint64_t pool_guid, uint64_t device_guid); extern char *spa_strdup(const char *); extern void spa_strfree(char *); -extern uint64_t spa_get_random(uint64_t range); extern uint64_t spa_generate_guid(spa_t *spa); extern void snprintf_blkptr(char *buf, size_t buflen, const blkptr_t *bp); extern void spa_freeze(spa_t *spa); diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h index ffb20e1fe..dbeb323ba 100644 --- a/include/sys/zfs_context.h +++ b/include/sys/zfs_context.h @@ -640,6 +640,21 @@ extern int lowbit64(uint64_t i); extern int random_get_bytes(uint8_t *ptr, size_t len); extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len); +static __inline__ uint32_t +random_in_range(uint32_t range) +{ + uint32_t r; + + ASSERT(range != 0); + + if (range == 1) + return (0); + + (void) random_get_pseudo_bytes((void *)&r, sizeof (r)); + + return (r % range); +} + extern void kernel_init(int mode); extern void kernel_fini(void); extern void random_init(void); |