Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

blk-throttle: Refactor tg_dispatch_time by extracting tg_dispatch_bps/iops_time

tg_dispatch_time() contained both bps and iops throttling logic. We now
split its internal logic into tg_dispatch_bps/iops_time() to improve code
consistency for future separation of the bps and iops queues.

Besides, merge time_before() from caller into throtl_extend_slice() to make
code cleaner.

Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Zizhi Wo <wozizhi@huaweicloud.com>
Link: https://lore.kernel.org/r/20250506020935.655574-3-wozizhi@huaweicloud.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Zizhi Wo and committed by
Jens Axboe
3660cd42 fd6c08b2

+55 -43
+55 -43
block/blk-throttle.c
··· 520 520 static inline void throtl_extend_slice(struct throtl_grp *tg, bool rw, 521 521 unsigned long jiffy_end) 522 522 { 523 + if (!time_before(tg->slice_end[rw], jiffy_end)) 524 + return; 525 + 523 526 throtl_set_slice_end(tg, rw, jiffy_end); 524 527 throtl_log(&tg->service_queue, 525 528 "[%c] extend slice start=%lu end=%lu jiffies=%lu", ··· 734 731 int io_allowed; 735 732 unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd; 736 733 737 - if (iops_limit == UINT_MAX) { 738 - return 0; 739 - } 740 - 741 734 jiffy_elapsed = jiffies - tg->slice_start[rw]; 742 735 743 736 /* Round up to the next throttle slice, wait time must be nonzero */ ··· 758 759 u64 extra_bytes; 759 760 unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd; 760 761 unsigned int bio_size = throtl_bio_data_size(bio); 761 - 762 - /* no need to throttle if this bio's bytes have been accounted */ 763 - if (bps_limit == U64_MAX || bio_flagged(bio, BIO_BPS_THROTTLED)) { 764 - return 0; 765 - } 766 762 767 763 jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw]; 768 764 ··· 788 794 } 789 795 790 796 /* 797 + * If previous slice expired, start a new one otherwise renew/extend existing 798 + * slice to make sure it is at least throtl_slice interval long since now. New 799 + * slice is started only for empty throttle group. If there is queued bio, that 800 + * means there should be an active slice and it should be extended instead. 801 + */ 802 + static void tg_update_slice(struct throtl_grp *tg, bool rw) 803 + { 804 + if (throtl_slice_used(tg, rw) && !(tg->service_queue.nr_queued[rw])) 805 + throtl_start_new_slice(tg, rw, true); 806 + else 807 + throtl_extend_slice(tg, rw, jiffies + tg->td->throtl_slice); 808 + } 809 + 810 + static unsigned long tg_dispatch_bps_time(struct throtl_grp *tg, struct bio *bio) 811 + { 812 + bool rw = bio_data_dir(bio); 813 + u64 bps_limit = tg_bps_limit(tg, rw); 814 + unsigned long bps_wait; 815 + 816 + /* no need to throttle if this bio's bytes have been accounted */ 817 + if (bps_limit == U64_MAX || tg->flags & THROTL_TG_CANCELING || 818 + bio_flagged(bio, BIO_BPS_THROTTLED)) 819 + return 0; 820 + 821 + tg_update_slice(tg, rw); 822 + bps_wait = tg_within_bps_limit(tg, bio, bps_limit); 823 + throtl_extend_slice(tg, rw, jiffies + bps_wait); 824 + 825 + return bps_wait; 826 + } 827 + 828 + static unsigned long tg_dispatch_iops_time(struct throtl_grp *tg, struct bio *bio) 829 + { 830 + bool rw = bio_data_dir(bio); 831 + u32 iops_limit = tg_iops_limit(tg, rw); 832 + unsigned long iops_wait; 833 + 834 + if (iops_limit == UINT_MAX || tg->flags & THROTL_TG_CANCELING) 835 + return 0; 836 + 837 + tg_update_slice(tg, rw); 838 + iops_wait = tg_within_iops_limit(tg, bio, iops_limit); 839 + throtl_extend_slice(tg, rw, jiffies + iops_wait); 840 + 841 + return iops_wait; 842 + } 843 + 844 + /* 791 845 * Returns approx number of jiffies to wait before this bio is with-in IO rate 792 846 * and can be dispatched. 793 847 */ 794 848 static unsigned long tg_dispatch_time(struct throtl_grp *tg, struct bio *bio) 795 849 { 796 850 bool rw = bio_data_dir(bio); 797 - unsigned long bps_wait, iops_wait, max_wait; 798 - u64 bps_limit = tg_bps_limit(tg, rw); 799 - u32 iops_limit = tg_iops_limit(tg, rw); 851 + unsigned long bps_wait, iops_wait; 800 852 801 853 /* 802 854 * Currently whole state machine of group depends on first bio ··· 853 813 BUG_ON(tg->service_queue.nr_queued[rw] && 854 814 bio != throtl_peek_queued(&tg->service_queue.queued[rw])); 855 815 856 - /* If tg->bps = -1, then BW is unlimited */ 857 - if ((bps_limit == U64_MAX && iops_limit == UINT_MAX) || 858 - tg->flags & THROTL_TG_CANCELING) 859 - return 0; 816 + bps_wait = tg_dispatch_bps_time(tg, bio); 817 + iops_wait = tg_dispatch_iops_time(tg, bio); 860 818 861 - /* 862 - * If previous slice expired, start a new one otherwise renew/extend 863 - * existing slice to make sure it is at least throtl_slice interval 864 - * long since now. New slice is started only for empty throttle group. 865 - * If there is queued bio, that means there should be an active 866 - * slice and it should be extended instead. 867 - */ 868 - if (throtl_slice_used(tg, rw) && !(tg->service_queue.nr_queued[rw])) 869 - throtl_start_new_slice(tg, rw, true); 870 - else { 871 - if (time_before(tg->slice_end[rw], 872 - jiffies + tg->td->throtl_slice)) 873 - throtl_extend_slice(tg, rw, 874 - jiffies + tg->td->throtl_slice); 875 - } 876 - 877 - bps_wait = tg_within_bps_limit(tg, bio, bps_limit); 878 - iops_wait = tg_within_iops_limit(tg, bio, iops_limit); 879 - if (bps_wait + iops_wait == 0) 880 - return 0; 881 - 882 - max_wait = max(bps_wait, iops_wait); 883 - 884 - if (time_before(tg->slice_end[rw], jiffies + max_wait)) 885 - throtl_extend_slice(tg, rw, jiffies + max_wait); 886 - 887 - return max_wait; 819 + return max(bps_wait, iops_wait); 888 820 } 889 821 890 822 static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)