aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-05-14 16:52:38 -0400
committerTejun Heo <tj@kernel.org>2013-05-14 16:52:38 -0400
commit2e48a530a3a7daebd0cc17866304a36d39b611de (patch)
tree6fc47a1a5b74966ff19f5287dc58fbcf3a541ee6 /block
parent6bc9c2b464fb89eab705da87aa4284171d942369 (diff)
blk-throttle: make throtl_pending_timer_fn() ready for hierarchy
throtl_pending_timer_fn() currently assumes that the parent_sq is the top level one and the bio's dispatched are ready to be issued; however, this assumption will be wrong with proper hierarchy support. This patch makes the following changes to make throtl_pending_timer_fn() ready for hiearchy. * If the parent_sq isn't the top-level one, update the parent throtl_grp's dispatch time and schedule the next dispatch as necessary. If the parent's dispatch time is now, repeat the function for the parent throtl_grp. * If the parent_sq is the top-level one, kick issue work_item as before. * The debug message printed by throtl_log() now prints out the service_queue's nr_queued[] instead of the total nr_queued as the latter becomes uninteresting and misleading with hierarchical dispatch. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Vivek Goyal <vgoyal@redhat.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-throttle.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 04202617fda5..bc65077f6e43 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -952,23 +952,33 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq)
952 * This timer is armed when a child throtl_grp with active bio's become 952 * This timer is armed when a child throtl_grp with active bio's become
953 * pending and queued on the service_queue's pending_tree and expires when 953 * pending and queued on the service_queue's pending_tree and expires when
954 * the first child throtl_grp should be dispatched. This function 954 * the first child throtl_grp should be dispatched. This function
955 * dispatches bio's from the children throtl_grps and kicks 955 * dispatches bio's from the children throtl_grps to the parent
956 * throtl_data->dispatch_work if there are bio's ready to be issued. 956 * service_queue.
957 *
958 * If the parent's parent is another throtl_grp, dispatching is propagated
959 * by either arming its pending_timer or repeating dispatch directly. If
960 * the top-level service_tree is reached, throtl_data->dispatch_work is
961 * kicked so that the ready bio's are issued.
957 */ 962 */
958static void throtl_pending_timer_fn(unsigned long arg) 963static void throtl_pending_timer_fn(unsigned long arg)
959{ 964{
960 struct throtl_service_queue *sq = (void *)arg; 965 struct throtl_service_queue *sq = (void *)arg;
966 struct throtl_grp *tg = sq_to_tg(sq);
961 struct throtl_data *td = sq_to_td(sq); 967 struct throtl_data *td = sq_to_td(sq);
962 struct request_queue *q = td->queue; 968 struct request_queue *q = td->queue;
963 bool dispatched = false; 969 struct throtl_service_queue *parent_sq;
970 bool dispatched;
964 int ret; 971 int ret;
965 972
966 spin_lock_irq(q->queue_lock); 973 spin_lock_irq(q->queue_lock);
974again:
975 parent_sq = sq->parent_sq;
976 dispatched = false;
967 977
968 while (true) { 978 while (true) {
969 throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u", 979 throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u",
970 td->nr_queued[READ] + td->nr_queued[WRITE], 980 sq->nr_queued[READ] + sq->nr_queued[WRITE],
971 td->nr_queued[READ], td->nr_queued[WRITE]); 981 sq->nr_queued[READ], sq->nr_queued[WRITE]);
972 982
973 ret = throtl_select_dispatch(sq); 983 ret = throtl_select_dispatch(sq);
974 if (ret) { 984 if (ret) {
@@ -985,9 +995,25 @@ static void throtl_pending_timer_fn(unsigned long arg)
985 spin_lock_irq(q->queue_lock); 995 spin_lock_irq(q->queue_lock);
986 } 996 }
987 997
988 if (dispatched) 998 if (!dispatched)
989 queue_work(kthrotld_workqueue, &td->dispatch_work); 999 goto out_unlock;
990 1000
1001 if (parent_sq) {
1002 /* @parent_sq is another throl_grp, propagate dispatch */
1003 if (tg->flags & THROTL_TG_WAS_EMPTY) {
1004 tg_update_disptime(tg);
1005 if (!throtl_schedule_next_dispatch(parent_sq, false)) {
1006 /* window is already open, repeat dispatching */
1007 sq = parent_sq;
1008 tg = sq_to_tg(sq);
1009 goto again;
1010 }
1011 }
1012 } else {
1013 /* reached the top-level, queue issueing */
1014 queue_work(kthrotld_workqueue, &td->dispatch_work);
1015 }
1016out_unlock:
991 spin_unlock_irq(q->queue_lock); 1017 spin_unlock_irq(q->queue_lock);
992} 1018}
993 1019