diff options
-rw-r--r-- | block/blk-throttle.c | 74 |
1 files changed, 20 insertions, 54 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 3960787358b6..7dbd0e695df0 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
@@ -85,9 +85,6 @@ struct throtl_grp { | |||
85 | unsigned long slice_start[2]; | 85 | unsigned long slice_start[2]; |
86 | unsigned long slice_end[2]; | 86 | unsigned long slice_end[2]; |
87 | 87 | ||
88 | /* Some throttle limits got updated for the group */ | ||
89 | int limits_changed; | ||
90 | |||
91 | /* Per cpu stats pointer */ | 88 | /* Per cpu stats pointer */ |
92 | struct tg_stats_cpu __percpu *stats_cpu; | 89 | struct tg_stats_cpu __percpu *stats_cpu; |
93 | 90 | ||
@@ -112,8 +109,6 @@ struct throtl_data | |||
112 | 109 | ||
113 | /* Work for dispatching throttled bios */ | 110 | /* Work for dispatching throttled bios */ |
114 | struct delayed_work throtl_work; | 111 | struct delayed_work throtl_work; |
115 | |||
116 | int limits_changed; | ||
117 | }; | 112 | }; |
118 | 113 | ||
119 | /* list and work item to allocate percpu group stats */ | 114 | /* list and work item to allocate percpu group stats */ |
@@ -223,7 +218,6 @@ static void throtl_pd_init(struct blkcg_gq *blkg) | |||
223 | RB_CLEAR_NODE(&tg->rb_node); | 218 | RB_CLEAR_NODE(&tg->rb_node); |
224 | bio_list_init(&tg->bio_lists[0]); | 219 | bio_list_init(&tg->bio_lists[0]); |
225 | bio_list_init(&tg->bio_lists[1]); | 220 | bio_list_init(&tg->bio_lists[1]); |
226 | tg->limits_changed = false; | ||
227 | 221 | ||
228 | tg->bps[READ] = -1; | 222 | tg->bps[READ] = -1; |
229 | tg->bps[WRITE] = -1; | 223 | tg->bps[WRITE] = -1; |
@@ -826,45 +820,6 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) | |||
826 | return nr_disp; | 820 | return nr_disp; |
827 | } | 821 | } |
828 | 822 | ||
829 | static void throtl_process_limit_change(struct throtl_data *td) | ||
830 | { | ||
831 | struct request_queue *q = td->queue; | ||
832 | struct blkcg_gq *blkg, *n; | ||
833 | |||
834 | if (!td->limits_changed) | ||
835 | return; | ||
836 | |||
837 | xchg(&td->limits_changed, false); | ||
838 | |||
839 | throtl_log(td, "limits changed"); | ||
840 | |||
841 | list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) { | ||
842 | struct throtl_grp *tg = blkg_to_tg(blkg); | ||
843 | |||
844 | if (!tg->limits_changed) | ||
845 | continue; | ||
846 | |||
847 | if (!xchg(&tg->limits_changed, false)) | ||
848 | continue; | ||
849 | |||
850 | throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu" | ||
851 | " riops=%u wiops=%u", tg->bps[READ], tg->bps[WRITE], | ||
852 | tg->iops[READ], tg->iops[WRITE]); | ||
853 | |||
854 | /* | ||
855 | * Restart the slices for both READ and WRITES. It | ||
856 | * might happen that a group's limit are dropped | ||
857 | * suddenly and we don't want to account recently | ||
858 | * dispatched IO with new low rate | ||
859 | */ | ||
860 | throtl_start_new_slice(td, tg, 0); | ||
861 | throtl_start_new_slice(td, tg, 1); | ||
862 | |||
863 | if (throtl_tg_on_rr(tg)) | ||
864 | tg_update_disptime(td, tg); | ||
865 | } | ||
866 | } | ||
867 | |||
868 | /* Dispatch throttled bios. Should be called without queue lock held. */ | 823 | /* Dispatch throttled bios. Should be called without queue lock held. */ |
869 | static int throtl_dispatch(struct request_queue *q) | 824 | static int throtl_dispatch(struct request_queue *q) |
870 | { | 825 | { |
@@ -876,8 +831,6 @@ static int throtl_dispatch(struct request_queue *q) | |||
876 | 831 | ||
877 | spin_lock_irq(q->queue_lock); | 832 | spin_lock_irq(q->queue_lock); |
878 | 833 | ||
879 | throtl_process_limit_change(td); | ||
880 | |||
881 | if (!total_nr_queued(td)) | 834 | if (!total_nr_queued(td)) |
882 | goto out; | 835 | goto out; |
883 | 836 | ||
@@ -925,8 +878,7 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) | |||
925 | 878 | ||
926 | struct delayed_work *dwork = &td->throtl_work; | 879 | struct delayed_work *dwork = &td->throtl_work; |
927 | 880 | ||
928 | /* schedule work if limits changed even if no bio is queued */ | 881 | if (total_nr_queued(td)) { |
929 | if (total_nr_queued(td) || td->limits_changed) { | ||
930 | mod_delayed_work(kthrotld_workqueue, dwork, delay); | 882 | mod_delayed_work(kthrotld_workqueue, dwork, delay); |
931 | throtl_log(td, "schedule work. delay=%lu jiffies=%lu", | 883 | throtl_log(td, "schedule work. delay=%lu jiffies=%lu", |
932 | delay, jiffies); | 884 | delay, jiffies); |
@@ -1023,10 +975,25 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, | |||
1023 | else | 975 | else |
1024 | *(unsigned int *)((void *)tg + cft->private) = ctx.v; | 976 | *(unsigned int *)((void *)tg + cft->private) = ctx.v; |
1025 | 977 | ||
1026 | /* XXX: we don't need the following deferred processing */ | 978 | throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", |
1027 | xchg(&tg->limits_changed, true); | 979 | tg->bps[READ], tg->bps[WRITE], |
1028 | xchg(&td->limits_changed, true); | 980 | tg->iops[READ], tg->iops[WRITE]); |
1029 | throtl_schedule_delayed_work(td, 0); | 981 | |
982 | /* | ||
983 | * We're already holding queue_lock and know @tg is valid. Let's | ||
984 | * apply the new config directly. | ||
985 | * | ||
986 | * Restart the slices for both READ and WRITES. It might happen | ||
987 | * that a group's limit are dropped suddenly and we don't want to | ||
988 | * account recently dispatched IO with new low rate. | ||
989 | */ | ||
990 | throtl_start_new_slice(td, tg, 0); | ||
991 | throtl_start_new_slice(td, tg, 1); | ||
992 | |||
993 | if (throtl_tg_on_rr(tg)) { | ||
994 | tg_update_disptime(td, tg); | ||
995 | throtl_schedule_next_dispatch(td); | ||
996 | } | ||
1030 | 997 | ||
1031 | blkg_conf_finish(&ctx); | 998 | blkg_conf_finish(&ctx); |
1032 | return 0; | 999 | return 0; |
@@ -1239,7 +1206,6 @@ int blk_throtl_init(struct request_queue *q) | |||
1239 | return -ENOMEM; | 1206 | return -ENOMEM; |
1240 | 1207 | ||
1241 | td->tg_service_tree = THROTL_RB_ROOT; | 1208 | td->tg_service_tree = THROTL_RB_ROOT; |
1242 | td->limits_changed = false; | ||
1243 | INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); | 1209 | INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); |
1244 | 1210 | ||
1245 | q->td = td; | 1211 | q->td = td; |