aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/blk-throttle.c96
1 files changed, 40 insertions, 56 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index a29f09240c0..32dd3e4b041 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -102,7 +102,7 @@ struct throtl_data
102 /* Work for dispatching throttled bios */ 102 /* Work for dispatching throttled bios */
103 struct delayed_work throtl_work; 103 struct delayed_work throtl_work;
104 104
105 atomic_t limits_changed; 105 bool limits_changed;
106}; 106};
107 107
108enum tg_state_flags { 108enum tg_state_flags {
@@ -201,6 +201,7 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
201 RB_CLEAR_NODE(&tg->rb_node); 201 RB_CLEAR_NODE(&tg->rb_node);
202 bio_list_init(&tg->bio_lists[0]); 202 bio_list_init(&tg->bio_lists[0]);
203 bio_list_init(&tg->bio_lists[1]); 203 bio_list_init(&tg->bio_lists[1]);
204 td->limits_changed = false;
204 205
205 /* 206 /*
206 * Take the initial reference that will be released on destroy 207 * Take the initial reference that will be released on destroy
@@ -737,34 +738,27 @@ static void throtl_process_limit_change(struct throtl_data *td)
737 struct throtl_grp *tg; 738 struct throtl_grp *tg;
738 struct hlist_node *pos, *n; 739 struct hlist_node *pos, *n;
739 740
740 if (!atomic_read(&td->limits_changed)) 741 if (!td->limits_changed)
741 return; 742 return;
742 743
743 throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed)); 744 xchg(&td->limits_changed, false);
744 745
745 /* 746 throtl_log(td, "limits changed");
746 * Make sure updates from throtl_update_blkio_group_read_bps() group
747 * of functions to tg->limits_changed are visible. We do not
748 * want update td->limits_changed to be visible but update to
749 * tg->limits_changed not being visible yet on this cpu. Hence
750 * the read barrier.
751 */
752 smp_rmb();
753 747
754 hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) { 748 hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
755 if (throtl_tg_on_rr(tg) && tg->limits_changed) { 749 if (!tg->limits_changed)
756 throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu" 750 continue;
757 " riops=%u wiops=%u", tg->bps[READ], 751
758 tg->bps[WRITE], tg->iops[READ], 752 if (!xchg(&tg->limits_changed, false))
759 tg->iops[WRITE]); 753 continue;
754
755 throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
756 " riops=%u wiops=%u", tg->bps[READ], tg->bps[WRITE],
757 tg->iops[READ], tg->iops[WRITE]);
758
759 if (throtl_tg_on_rr(tg))
760 tg_update_disptime(td, tg); 760 tg_update_disptime(td, tg);
761 tg->limits_changed = false;
762 }
763 } 761 }
764
765 smp_mb__before_atomic_dec();
766 atomic_dec(&td->limits_changed);
767 smp_mb__after_atomic_dec();
768} 762}
769 763
770/* Dispatch throttled bios. Should be called without queue lock held. */ 764/* Dispatch throttled bios. Should be called without queue lock held. */
@@ -898,6 +892,15 @@ void throtl_unlink_blkio_group(void *key, struct blkio_group *blkg)
898 spin_unlock_irqrestore(td->queue->queue_lock, flags); 892 spin_unlock_irqrestore(td->queue->queue_lock, flags);
899} 893}
900 894
895static void throtl_update_blkio_group_common(struct throtl_data *td,
896 struct throtl_grp *tg)
897{
898 xchg(&tg->limits_changed, true);
899 xchg(&td->limits_changed, true);
900 /* Schedule a work now to process the limit change */
901 throtl_schedule_delayed_work(td, 0);
902}
903
901/* 904/*
902 * For all update functions, key should be a valid pointer because these 905 * For all update functions, key should be a valid pointer because these
903 * update functions are called under blkcg_lock, that means, blkg is 906 * update functions are called under blkcg_lock, that means, blkg is
@@ -911,61 +914,40 @@ static void throtl_update_blkio_group_read_bps(void *key,
911 struct blkio_group *blkg, u64 read_bps) 914 struct blkio_group *blkg, u64 read_bps)
912{ 915{
913 struct throtl_data *td = key; 916 struct throtl_data *td = key;
917 struct throtl_grp *tg = tg_of_blkg(blkg);
914 918
915 tg_of_blkg(blkg)->bps[READ] = read_bps; 919 tg->bps[READ] = read_bps;
916 /* Make sure read_bps is updated before setting limits_changed */ 920 throtl_update_blkio_group_common(td, tg);
917 smp_wmb();
918 tg_of_blkg(blkg)->limits_changed = true;
919
920 /* Make sure tg->limits_changed is updated before td->limits_changed */
921 smp_mb__before_atomic_inc();
922 atomic_inc(&td->limits_changed);
923 smp_mb__after_atomic_inc();
924
925 /* Schedule a work now to process the limit change */
926 throtl_schedule_delayed_work(td, 0);
927} 921}
928 922
929static void throtl_update_blkio_group_write_bps(void *key, 923static void throtl_update_blkio_group_write_bps(void *key,
930 struct blkio_group *blkg, u64 write_bps) 924 struct blkio_group *blkg, u64 write_bps)
931{ 925{
932 struct throtl_data *td = key; 926 struct throtl_data *td = key;
927 struct throtl_grp *tg = tg_of_blkg(blkg);
933 928
934 tg_of_blkg(blkg)->bps[WRITE] = write_bps; 929 tg->bps[WRITE] = write_bps;
935 smp_wmb(); 930 throtl_update_blkio_group_common(td, tg);
936 tg_of_blkg(blkg)->limits_changed = true;
937 smp_mb__before_atomic_inc();
938 atomic_inc(&td->limits_changed);
939 smp_mb__after_atomic_inc();
940 throtl_schedule_delayed_work(td, 0);
941} 931}
942 932
943static void throtl_update_blkio_group_read_iops(void *key, 933static void throtl_update_blkio_group_read_iops(void *key,
944 struct blkio_group *blkg, unsigned int read_iops) 934 struct blkio_group *blkg, unsigned int read_iops)
945{ 935{
946 struct throtl_data *td = key; 936 struct throtl_data *td = key;
937 struct throtl_grp *tg = tg_of_blkg(blkg);
947 938
948 tg_of_blkg(blkg)->iops[READ] = read_iops; 939 tg->iops[READ] = read_iops;
949 smp_wmb(); 940 throtl_update_blkio_group_common(td, tg);
950 tg_of_blkg(blkg)->limits_changed = true;
951 smp_mb__before_atomic_inc();
952 atomic_inc(&td->limits_changed);
953 smp_mb__after_atomic_inc();
954 throtl_schedule_delayed_work(td, 0);
955} 941}
956 942
957static void throtl_update_blkio_group_write_iops(void *key, 943static void throtl_update_blkio_group_write_iops(void *key,
958 struct blkio_group *blkg, unsigned int write_iops) 944 struct blkio_group *blkg, unsigned int write_iops)
959{ 945{
960 struct throtl_data *td = key; 946 struct throtl_data *td = key;
947 struct throtl_grp *tg = tg_of_blkg(blkg);
961 948
962 tg_of_blkg(blkg)->iops[WRITE] = write_iops; 949 tg->iops[WRITE] = write_iops;
963 smp_wmb(); 950 throtl_update_blkio_group_common(td, tg);
964 tg_of_blkg(blkg)->limits_changed = true;
965 smp_mb__before_atomic_inc();
966 atomic_inc(&td->limits_changed);
967 smp_mb__after_atomic_inc();
968 throtl_schedule_delayed_work(td, 0);
969} 951}
970 952
971static void throtl_shutdown_wq(struct request_queue *q) 953static void throtl_shutdown_wq(struct request_queue *q)
@@ -1012,6 +994,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
1012 */ 994 */
1013 update_disptime = false; 995 update_disptime = false;
1014 goto queue_bio; 996 goto queue_bio;
997
1015 } 998 }
1016 999
1017 /* Bio is with-in rate limit of group */ 1000 /* Bio is with-in rate limit of group */
@@ -1052,7 +1035,7 @@ int blk_throtl_init(struct request_queue *q)
1052 1035
1053 INIT_HLIST_HEAD(&td->tg_list); 1036 INIT_HLIST_HEAD(&td->tg_list);
1054 td->tg_service_tree = THROTL_RB_ROOT; 1037 td->tg_service_tree = THROTL_RB_ROOT;
1055 atomic_set(&td->limits_changed, 0); 1038 td->limits_changed = false;
1056 1039
1057 /* Init root group */ 1040 /* Init root group */
1058 tg = &td->root_tg; 1041 tg = &td->root_tg;
@@ -1064,6 +1047,7 @@ int blk_throtl_init(struct request_queue *q)
1064 /* Practically unlimited BW */ 1047 /* Practically unlimited BW */
1065 tg->bps[0] = tg->bps[1] = -1; 1048 tg->bps[0] = tg->bps[1] = -1;
1066 tg->iops[0] = tg->iops[1] = -1; 1049 tg->iops[0] = tg->iops[1] = -1;
1050 td->limits_changed = false;
1067 1051
1068 /* 1052 /*
1069 * Set root group reference to 2. One reference will be dropped when 1053 * Set root group reference to 2. One reference will be dropped when