Skip to content

Commit 9c18ea7

Browse files
author
Kent Overstreet
committed
bcachefs: bch2_get_random_u64_below()
steal the (clever) algorithm from get_random_u32_below() this fixes a bug where we were passing roundup_pow_of_two() a 64 bit number - we're squaring device latencies now: [ +1.681698] ------------[ cut here ]------------ [ +0.000010] UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 [ +0.000011] shift exponent 64 is too large for 64-bit type 'long unsigned int' [ +0.000011] CPU: 1 UID: 0 PID: 196 Comm: kworker/u32:13 Not tainted 6.14.0-rc6-dave+ kernel-patches#10 [ +0.000012] Hardware name: ASUS System Product Name/PRIME B460I-PLUS, BIOS 1301 07/13/2021 [ +0.000005] Workqueue: events_unbound __bch2_read_endio [bcachefs] [ +0.000354] Call Trace: [ +0.000005] <TASK> [ +0.000007] dump_stack_lvl+0x5d/0x80 [ +0.000018] ubsan_epilogue+0x5/0x30 [ +0.000008] __ubsan_handle_shift_out_of_bounds.cold+0x61/0xe6 [ +0.000011] bch2_rand_range.cold+0x17/0x20 [bcachefs] [ +0.000231] bch2_bkey_pick_read_device+0x547/0x920 [bcachefs] [ +0.000229] __bch2_read_extent+0x1e4/0x18e0 [bcachefs] [ +0.000241] ? bch2_btree_iter_peek_slot+0x3df/0x800 [bcachefs] [ +0.000180] ? bch2_read_retry_nodecode+0x270/0x330 [bcachefs] [ +0.000230] bch2_read_retry_nodecode+0x270/0x330 [bcachefs] [ +0.000230] bch2_rbio_retry+0x1fa/0x600 [bcachefs] [ +0.000224] ? bch2_printbuf_make_room+0x71/0xb0 [bcachefs] [ +0.000243] ? bch2_read_csum_err+0x4a4/0x610 [bcachefs] [ +0.000278] bch2_read_csum_err+0x4a4/0x610 [bcachefs] [ +0.000227] ? __bch2_read_endio+0x58b/0x870 [bcachefs] [ +0.000220] __bch2_read_endio+0x58b/0x870 [bcachefs] [ +0.000268] ? try_to_wake_up+0x31c/0x7f0 [ +0.000011] ? process_one_work+0x176/0x330 [ +0.000008] process_one_work+0x176/0x330 [ +0.000008] worker_thread+0x252/0x390 [ +0.000008] ? __pfx_worker_thread+0x10/0x10 [ +0.000006] kthread+0xec/0x230 [ +0.000011] ? __pfx_kthread+0x10/0x10 [ +0.000009] ret_from_fork+0x31/0x50 [ +0.000009] ? __pfx_kthread+0x10/0x10 [ +0.000008] ret_from_fork_asm+0x1a/0x30 [ +0.000012] </TASK> [ +0.000046] ---[ end trace ]--- Reported-by: Roland Vet <[email protected]> Signed-off-by: Kent Overstreet <[email protected]>
1 parent 69a5a13 commit 9c18ea7

File tree

3 files changed

+16
-11
lines changed

3 files changed

+16
-11
lines changed

fs/bcachefs/extents.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ static inline bool ptr_better(struct bch_fs *c,
9999

100100
/* Pick at random, biased in favor of the faster device: */
101101

102-
return bch2_rand_range(l1 + l2) > l1;
102+
return bch2_get_random_u64_below(l1 + l2) > l1;
103103
}
104104

105105
if (bch2_force_reconstruct_read)

fs/bcachefs/util.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -653,19 +653,24 @@ int bch2_bio_alloc_pages(struct bio *bio, size_t size, gfp_t gfp_mask)
653653
return 0;
654654
}
655655

656-
size_t bch2_rand_range(size_t max)
656+
u64 bch2_get_random_u64_below(u64 ceil)
657657
{
658-
size_t rand;
658+
if (ceil <= U32_MAX)
659+
return __get_random_u32_below(ceil);
659660

660-
if (!max)
661-
return 0;
661+
/* this is the same (clever) algorithm as in __get_random_u32_below() */
662+
u64 rand = get_random_u64();
663+
u64 mult = ceil * rand;
662664

663-
do {
664-
rand = get_random_long();
665-
rand &= roundup_pow_of_two(max) - 1;
666-
} while (rand >= max);
665+
if (unlikely(mult < ceil)) {
666+
u64 bound = -ceil % ceil;
667+
while (unlikely(mult < bound)) {
668+
rand = get_random_u64();
669+
mult = ceil * rand;
670+
}
671+
}
667672

668-
return rand;
673+
return mul_u64_u64_shr(ceil, rand, 64);
669674
}
670675

671676
void memcpy_to_bio(struct bio *dst, struct bvec_iter dst_iter, const void *src)

fs/bcachefs/util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ do { \
401401
_ret; \
402402
})
403403

404-
size_t bch2_rand_range(size_t);
404+
u64 bch2_get_random_u64_below(u64);
405405

406406
void memcpy_to_bio(struct bio *, struct bvec_iter, const void *);
407407
void memcpy_from_bio(void *, struct bio *, struct bvec_iter);

0 commit comments

Comments
 (0)