summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKunhai Dai <daikunhai@didiglobal.com>2026-10-19 08:54:11 -0400
committerJens Axboe <axboe@kernel.dk>2026-10-29 07:38:28 -0600
commitc810ee88cdab27f443c32270dc7c0eaad2cca3f8 (patch)
treeebc38b0c6425cf5bde16a2b7c70bdd39f33b497f
parent08ebf69c78a02afb39b7728f3358c09bc4cf067d (diff)
downloadlinux-c810ee88cdab27f443c32270dc7c0eaad2cca3f8.tar.gz
linux-c810ee88cdab27f443c32270dc7c0eaad2cca3f8.zip
blk-iocost: abort weight transfer on invalid donation weights
transfer_surpluses() warns and then keeps going when the donation calculation produced invalid weights. The following propagation can then divide by a zero hweight_inuse, so the warning is immediately followed by a divide error. When the check trips, abandon this period's donation transfer and release the walk lists. This trades one period without donation for not crashing; the invalid state is not expected on the normal path. Developed with assistance from Claude Code (Anthropic): the assistant analysed the failure path, drafted the change and ran the checks listed below. The author reviewed the result and remains responsible for it. Fixes: e08d02aa5fc9 ("blk-iocost: implement Andy's method for donation weight updates") Cc: stable@vger.kernel.org Signed-off-by: Kunhai Dai <daikunhai@didiglobal.com> Tested-by: Tao Cui <cuitao@kylinos.cn> Reviewed-by: Tao Cui <cuitao@kylinos.cn> Acked-by: Tejun Heo <tj@kernel.org> Link: https://patch.msgid.link/20261019125412.3123895-2-daikunhai@didiglobal.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/blk-iocost.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 47bea7f31408..1118a8a1f079 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -1961,6 +1961,7 @@ static void transfer_surpluses(struct list_head *surpluses, struct ioc_now *now)
pr_cont(": active=%u donating=%u after=%u\n",
iocg->hweight_active, iocg->hweight_donating,
iocg->hweight_after_donation);
+ goto out;
}
}
@@ -2059,6 +2060,7 @@ static void transfer_surpluses(struct list_head *surpluses, struct ioc_now *now)
__propagate_weights(iocg, iocg->active, inuse, true, now);
}
+out:
/* walk list should be dissolved after use */
list_for_each_entry_safe(iocg, tiocg, &inner_walk, walk_list)
list_del_init(&iocg->walk_list);