aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAlexander Motin <[email protected]>2021-06-22 19:35:23 -0400
committerTony Hutter <[email protected]>2021-09-14 12:10:17 -0700
commitf3969ea78b5f54935474d49455cf9c4d6a1e107a (patch)
tree38dbfbee2cd0bbd24bbc642e2023d3f20bd82b6f /include
parent6fe6192796f6835163523db94130fb842022f6cf (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.h22
-rw-r--r--include/os/linux/spl/sys/random.h15
-rw-r--r--include/sys/spa.h1
-rw-r--r--include/sys/zfs_context.h15
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);