diff options
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r-- | block/blk-throttle.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 381b09bb562b..e36cc10a346c 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
@@ -20,6 +20,11 @@ static int throtl_quantum = 32; | |||
20 | /* Throttling is performed over 100ms slice and after that slice is renewed */ | 20 | /* Throttling is performed over 100ms slice and after that slice is renewed */ |
21 | static unsigned long throtl_slice = HZ/10; /* 100 ms */ | 21 | static unsigned long throtl_slice = HZ/10; /* 100 ms */ |
22 | 22 | ||
23 | /* A workqueue to queue throttle related work */ | ||
24 | static struct workqueue_struct *kthrotld_workqueue; | ||
25 | static void throtl_schedule_delayed_work(struct throtl_data *td, | ||
26 | unsigned long delay); | ||
27 | |||
23 | struct throtl_rb_root { | 28 | struct throtl_rb_root { |
24 | struct rb_root rb; | 29 | struct rb_root rb; |
25 | struct rb_node *left; | 30 | struct rb_node *left; |
@@ -168,7 +173,15 @@ static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td, | |||
168 | * tree of blkg (instead of traversing through hash list all | 173 | * tree of blkg (instead of traversing through hash list all |
169 | * the time. | 174 | * the time. |
170 | */ | 175 | */ |
171 | tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key)); | 176 | |
177 | /* | ||
178 | * This is the common case when there are no blkio cgroups. | ||
179 | * Avoid lookup in this case | ||
180 | */ | ||
181 | if (blkcg == &blkio_root_cgroup) | ||
182 | tg = &td->root_tg; | ||
183 | else | ||
184 | tg = tg_of_blkg(blkiocg_lookup_group(blkcg, key)); | ||
172 | 185 | ||
173 | /* Fill in device details for root group */ | 186 | /* Fill in device details for root group */ |
174 | if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { | 187 | if (tg && !tg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { |
@@ -337,10 +350,9 @@ static void throtl_schedule_next_dispatch(struct throtl_data *td) | |||
337 | update_min_dispatch_time(st); | 350 | update_min_dispatch_time(st); |
338 | 351 | ||
339 | if (time_before_eq(st->min_disptime, jiffies)) | 352 | if (time_before_eq(st->min_disptime, jiffies)) |
340 | throtl_schedule_delayed_work(td->queue, 0); | 353 | throtl_schedule_delayed_work(td, 0); |
341 | else | 354 | else |
342 | throtl_schedule_delayed_work(td->queue, | 355 | throtl_schedule_delayed_work(td, (st->min_disptime - jiffies)); |
343 | (st->min_disptime - jiffies)); | ||
344 | } | 356 | } |
345 | 357 | ||
346 | static inline void | 358 | static inline void |
@@ -807,10 +819,10 @@ void blk_throtl_work(struct work_struct *work) | |||
807 | } | 819 | } |
808 | 820 | ||
809 | /* Call with queue lock held */ | 821 | /* Call with queue lock held */ |
810 | void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay) | 822 | static void |
823 | throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) | ||
811 | { | 824 | { |
812 | 825 | ||
813 | struct throtl_data *td = q->td; | ||
814 | struct delayed_work *dwork = &td->throtl_work; | 826 | struct delayed_work *dwork = &td->throtl_work; |
815 | 827 | ||
816 | if (total_nr_queued(td) > 0) { | 828 | if (total_nr_queued(td) > 0) { |
@@ -819,12 +831,11 @@ void throtl_schedule_delayed_work(struct request_queue *q, unsigned long delay) | |||
819 | * Cancel that and schedule a new one. | 831 | * Cancel that and schedule a new one. |
820 | */ | 832 | */ |
821 | __cancel_delayed_work(dwork); | 833 | __cancel_delayed_work(dwork); |
822 | kblockd_schedule_delayed_work(q, dwork, delay); | 834 | queue_delayed_work(kthrotld_workqueue, dwork, delay); |
823 | throtl_log(td, "schedule work. delay=%lu jiffies=%lu", | 835 | throtl_log(td, "schedule work. delay=%lu jiffies=%lu", |
824 | delay, jiffies); | 836 | delay, jiffies); |
825 | } | 837 | } |
826 | } | 838 | } |
827 | EXPORT_SYMBOL(throtl_schedule_delayed_work); | ||
828 | 839 | ||
829 | static void | 840 | static void |
830 | throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg) | 841 | throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg) |
@@ -912,7 +923,7 @@ static void throtl_update_blkio_group_read_bps(void *key, | |||
912 | smp_mb__after_atomic_inc(); | 923 | smp_mb__after_atomic_inc(); |
913 | 924 | ||
914 | /* Schedule a work now to process the limit change */ | 925 | /* Schedule a work now to process the limit change */ |
915 | throtl_schedule_delayed_work(td->queue, 0); | 926 | throtl_schedule_delayed_work(td, 0); |
916 | } | 927 | } |
917 | 928 | ||
918 | static void throtl_update_blkio_group_write_bps(void *key, | 929 | static void throtl_update_blkio_group_write_bps(void *key, |
@@ -926,7 +937,7 @@ static void throtl_update_blkio_group_write_bps(void *key, | |||
926 | smp_mb__before_atomic_inc(); | 937 | smp_mb__before_atomic_inc(); |
927 | atomic_inc(&td->limits_changed); | 938 | atomic_inc(&td->limits_changed); |
928 | smp_mb__after_atomic_inc(); | 939 | smp_mb__after_atomic_inc(); |
929 | throtl_schedule_delayed_work(td->queue, 0); | 940 | throtl_schedule_delayed_work(td, 0); |
930 | } | 941 | } |
931 | 942 | ||
932 | static void throtl_update_blkio_group_read_iops(void *key, | 943 | static void throtl_update_blkio_group_read_iops(void *key, |
@@ -940,7 +951,7 @@ static void throtl_update_blkio_group_read_iops(void *key, | |||
940 | smp_mb__before_atomic_inc(); | 951 | smp_mb__before_atomic_inc(); |
941 | atomic_inc(&td->limits_changed); | 952 | atomic_inc(&td->limits_changed); |
942 | smp_mb__after_atomic_inc(); | 953 | smp_mb__after_atomic_inc(); |
943 | throtl_schedule_delayed_work(td->queue, 0); | 954 | throtl_schedule_delayed_work(td, 0); |
944 | } | 955 | } |
945 | 956 | ||
946 | static void throtl_update_blkio_group_write_iops(void *key, | 957 | static void throtl_update_blkio_group_write_iops(void *key, |
@@ -954,7 +965,7 @@ static void throtl_update_blkio_group_write_iops(void *key, | |||
954 | smp_mb__before_atomic_inc(); | 965 | smp_mb__before_atomic_inc(); |
955 | atomic_inc(&td->limits_changed); | 966 | atomic_inc(&td->limits_changed); |
956 | smp_mb__after_atomic_inc(); | 967 | smp_mb__after_atomic_inc(); |
957 | throtl_schedule_delayed_work(td->queue, 0); | 968 | throtl_schedule_delayed_work(td, 0); |
958 | } | 969 | } |
959 | 970 | ||
960 | void throtl_shutdown_timer_wq(struct request_queue *q) | 971 | void throtl_shutdown_timer_wq(struct request_queue *q) |
@@ -1127,6 +1138,10 @@ void blk_throtl_exit(struct request_queue *q) | |||
1127 | 1138 | ||
1128 | static int __init throtl_init(void) | 1139 | static int __init throtl_init(void) |
1129 | { | 1140 | { |
1141 | kthrotld_workqueue = alloc_workqueue("kthrotld", WQ_MEM_RECLAIM, 0); | ||
1142 | if (!kthrotld_workqueue) | ||
1143 | panic("Failed to create kthrotld\n"); | ||
1144 | |||
1130 | blkio_policy_register(&blkio_policy_throtl); | 1145 | blkio_policy_register(&blkio_policy_throtl); |
1131 | return 0; | 1146 | return 0; |
1132 | } | 1147 | } |