Commit 121cde81 authored by Tejun Heo's avatar Tejun Heo Committed by Guo Mengqi
Browse files

blk-iocost: Fix an UBSAN shift-out-of-bounds warning

stable inclusion
from stable-v5.10.210
commit 9f56f38331171c9a19754004f0664686d67ee48d
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9DNCI

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=9f56f38331171c9a19754004f0664686d67ee48d



--------------------------------

[ 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: default avatarBreno Leitão <leitao@debian.org>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Fixes: 5160a5a5 ("blk-iocost: implement delay adjustment hysteresis")
Link: https://lore.kernel.org/r/ZVvc9L_CYk5LO1fT@slm.duckdns.org


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWang Hai <wanghai38@huawei.com>
parent 719747ca
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1315,6 +1315,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)