--- /dev/null
+From bc10e9eece7a6e8b8ed22460e9c3085502ae0320 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Nov 2023 12:25:56 -1000
+Subject: blk-iocost: Fix an UBSAN shift-out-of-bounds warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 2a427b49d02995ea4a6ff93a1432c40fa4d36821 ]
+
+When iocg_kick_delay() is called from a CPU different than the one which set
+the delay, @now may be in the past of @iocg->delay_at leading to the
+following warning:
+
+ UBSAN: shift-out-of-bounds in block/blk-iocost.c:1359:23
+ shift exponent 18446744073709 is too large for 64-bit type 'u64' (aka 'unsigned long long')
+ ...
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x79/0xc0
+ __ubsan_handle_shift_out_of_bounds+0x2ab/0x300
+ iocg_kick_delay+0x222/0x230
+ ioc_rqos_merge+0x1d7/0x2c0
+ __rq_qos_merge+0x2c/0x80
+ bio_attempt_back_merge+0x83/0x190
+ blk_attempt_plug_merge+0x101/0x150
+ blk_mq_submit_bio+0x2b1/0x720
+ submit_bio_noacct_nocheck+0x320/0x3e0
+ __swap_writepage+0x2ab/0x9d0
+
+The underflow itself doesn't really affect the behavior in any meaningful
+way; however, the past timestamp may exaggerate the delay amount calculated
+later in the code, which shouldn't be a material problem given the nature of
+the delay mechanism.
+
+If @now is in the past, this CPU is racing another CPU which recently set up
+the delay and there's nothing this CPU can contribute w.r.t. the delay.
+Let's bail early from iocg_kick_delay() in such cases.
+
+Reported-by: Breno Leitão <leitao@debian.org>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Fixes: 5160a5a53c0c ("blk-iocost: implement delay adjustment hysteresis")
+Link: https://lore.kernel.org/r/ZVvc9L_CYk5LO1fT@slm.duckdns.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-iocost.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/block/blk-iocost.c b/block/blk-iocost.c
+index 7ba7c4e4e4c9..63a8fb456b28 100644
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -1296,6 +1296,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
+
+ lockdep_assert_held(&iocg->waitq.lock);
+
++ /*
++ * If the delay is set by another CPU, we may be in the past. No need to
++ * change anything if so. This avoids decay calculation underflow.
++ */
++ if (time_before64(now->now, iocg->delay_at))
++ return false;
++
+ /* calculate the current delay in effect - 1/2 every second */
+ tdelta = now->now - iocg->delay_at;
+ if (iocg->delay)
+--
+2.43.0
+