Skip to content

Commit b84b8b1

Browse files
committed
Optimize spa_get_random().
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(). On FreeBSD directly map spa_get_random() 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. Signed-off-by: Alexander Motin <[email protected]> Sponsored-By: iXsystems, Inc.
1 parent 8d5f211 commit b84b8b1

File tree

6 files changed

+65
-24
lines changed

6 files changed

+65
-24
lines changed

include/os/freebsd/spl/sys/random.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
#define _OPENSOLARIS_SYS_RANDOM_H_
3131

3232
#include_next <sys/random.h>
33+
#if __FreeBSD_version >= 1300108
34+
#include <sys/prng.h>
35+
#endif
3336

3437
static inline int
3538
random_get_bytes(uint8_t *p, size_t s)
@@ -45,4 +48,23 @@ random_get_pseudo_bytes(uint8_t *p, size_t s)
4548
return (0);
4649
}
4750

51+
static inline uint32_t
52+
spa_get_random(uint32_t range)
53+
{
54+
#if __FreeBSD_version >= 1300108
55+
return (prng32_bounded(range));
56+
#else
57+
uint32_t r;
58+
59+
ASSERT(range != 0);
60+
61+
if (range == 1)
62+
return (0);
63+
64+
(void) random_get_pseudo_bytes((void *)&r, sizeof (r));
65+
66+
return (r % range);
67+
#endif
68+
}
69+
4870
#endif /* !_OPENSOLARIS_SYS_RANDOM_H_ */

include/os/linux/spl/sys/random.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,19 @@ random_get_bytes(uint8_t *ptr, size_t len)
3636

3737
extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len);
3838

39+
static __inline__ uint32_t
40+
spa_get_random(uint32_t range)
41+
{
42+
uint32_t r;
43+
44+
ASSERT(range != 0);
45+
46+
if (range == 1)
47+
return (0);
48+
49+
(void) random_get_pseudo_bytes((void *)&r, sizeof (r));
50+
51+
return (r % range);
52+
}
53+
3954
#endif /* _SPL_RANDOM_H */

include/sys/spa.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,6 @@ extern spa_t *spa_by_guid(uint64_t pool_guid, uint64_t device_guid);
10661066
extern boolean_t spa_guid_exists(uint64_t pool_guid, uint64_t device_guid);
10671067
extern char *spa_strdup(const char *);
10681068
extern void spa_strfree(char *);
1069-
extern uint64_t spa_get_random(uint64_t range);
10701069
extern uint64_t spa_generate_guid(spa_t *spa);
10711070
extern void snprintf_blkptr(char *buf, size_t buflen, const blkptr_t *bp);
10721071
extern void spa_freeze(spa_t *spa);

include/sys/zfs_context.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,21 @@ extern int lowbit64(uint64_t i);
646646
extern int random_get_bytes(uint8_t *ptr, size_t len);
647647
extern int random_get_pseudo_bytes(uint8_t *ptr, size_t len);
648648

649+
static __inline__ uint32_t
650+
spa_get_random(uint32_t range)
651+
{
652+
uint32_t r;
653+
654+
ASSERT(range != 0);
655+
656+
if (range == 1)
657+
return (0);
658+
659+
(void) random_get_pseudo_bytes((void *)&r, sizeof (r));
660+
661+
return (r % range);
662+
}
663+
649664
extern void kernel_init(int mode);
650665
extern void kernel_fini(void);
651666
extern void random_init(void);

module/zfs/spa_misc.c

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,32 +1494,21 @@ spa_strfree(char *s)
14941494
kmem_free(s, strlen(s) + 1);
14951495
}
14961496

1497-
uint64_t
1498-
spa_get_random(uint64_t range)
1499-
{
1500-
uint64_t r;
1501-
1502-
ASSERT(range != 0);
1503-
1504-
if (range == 1)
1505-
return (0);
1506-
1507-
(void) random_get_pseudo_bytes((void *)&r, sizeof (uint64_t));
1508-
1509-
return (r % range);
1510-
}
1511-
15121497
uint64_t
15131498
spa_generate_guid(spa_t *spa)
15141499
{
1515-
uint64_t guid = spa_get_random(-1ULL);
1500+
uint64_t guid;
15161501

15171502
if (spa != NULL) {
1518-
while (guid == 0 || spa_guid_exists(spa_guid(spa), guid))
1519-
guid = spa_get_random(-1ULL);
1503+
do {
1504+
(void) random_get_pseudo_bytes((void *)&guid,
1505+
sizeof (guid));
1506+
} while (guid == 0 || spa_guid_exists(spa_guid(spa), guid));
15201507
} else {
1521-
while (guid == 0 || spa_guid_exists(guid, 0))
1522-
guid = spa_get_random(-1ULL);
1508+
do {
1509+
(void) random_get_pseudo_bytes((void *)&guid,
1510+
sizeof (guid));
1511+
} while (guid == 0 || spa_guid_exists(guid, 0));
15231512
}
15241513

15251514
return (guid);
@@ -2888,7 +2877,6 @@ EXPORT_SYMBOL(spa_maxdnodesize);
28882877
EXPORT_SYMBOL(spa_guid_exists);
28892878
EXPORT_SYMBOL(spa_strdup);
28902879
EXPORT_SYMBOL(spa_strfree);
2891-
EXPORT_SYMBOL(spa_get_random);
28922880
EXPORT_SYMBOL(spa_generate_guid);
28932881
EXPORT_SYMBOL(snprintf_blkptr);
28942882
EXPORT_SYMBOL(spa_freeze);

module/zfs/zil.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ zil_init_log_chain(zilog_t *zilog, blkptr_t *bp)
205205
{
206206
zio_cksum_t *zc = &bp->blk_cksum;
207207

208-
zc->zc_word[ZIL_ZC_GUID_0] = spa_get_random(-1ULL);
209-
zc->zc_word[ZIL_ZC_GUID_1] = spa_get_random(-1ULL);
208+
(void) random_get_pseudo_bytes((void *)&zc->zc_word[ZIL_ZC_GUID_0],
209+
sizeof (zc->zc_word[ZIL_ZC_GUID_0]));
210+
(void) random_get_pseudo_bytes((void *)&zc->zc_word[ZIL_ZC_GUID_1],
211+
sizeof (zc->zc_word[ZIL_ZC_GUID_1]));
210212
zc->zc_word[ZIL_ZC_OBJSET] = dmu_objset_id(zilog->zl_os);
211213
zc->zc_word[ZIL_ZC_SEQ] = 1ULL;
212214
}

0 commit comments

Comments
 (0)