Skip to content

Commit

Permalink
blk-throttle: make blk_throtl_bio() ready for hierarchy
Browse files Browse the repository at this point in the history
Currently, blk_throtl_bio() issues the passed in bio directly if it's
within limits of its associated tg (throtl_grp).  This behavior
becomes incorrect with hierarchy support as the bio should be
accounted to and throttled by the ancestor throtl_grps too.

This patch makes the direct issue path of blk_throtl_bio() to loop
until it reaches the top-level service_queue or gets throttled.  If
the former, the bio can be issued directly; otherwise, it gets queued
at the first layer it was above limits.

As tg->parent_sq is always the top-level service queue currently, this
patch in itself doesn't make any behavior differences.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
  • Loading branch information
Tejun Heo committed May 14, 2013
1 parent 2a12f0d commit 9e660ac
Showing 1 changed file with 20 additions and 7 deletions.
27 changes: 20 additions & 7 deletions block/blk-throttle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,12 +1239,16 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)

sq = &tg->service_queue;

/* throtl is FIFO - if other bios are already queued, should queue */
if (sq->nr_queued[rw])
goto queue_bio;
while (true) {
/* throtl is FIFO - if bios are already queued, should queue */
if (sq->nr_queued[rw])
break;

/* Bio is with-in rate limit of group */
if (tg_may_dispatch(tg, bio, NULL)) {
/* if above limits, break to queue */
if (!tg_may_dispatch(tg, bio, NULL))
break;

/* within limits, let's charge and dispatch directly */
throtl_charge_bio(tg, bio);

/*
Expand All @@ -1259,10 +1263,19 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
* So keep on trimming slice even if bio is not queued.
*/
throtl_trim_slice(tg, rw);
goto out_unlock;

/*
* @bio passed through this layer without being throttled.
* Climb up the ladder. If we''re already at the top, it
* can be executed directly.
*/
sq = sq->parent_sq;
tg = sq_to_tg(sq);
if (!tg)
goto out_unlock;
}

queue_bio:
/* out-of-limit, queue to @tg */
throtl_log(sq, "[%c] bio. bdisp=%llu sz=%u bps=%llu iodisp=%u iops=%u queued=%d/%d",
rw == READ ? 'R' : 'W',
tg->bytes_disp[rw], bio->bi_size, tg->bps[rw],
Expand Down

0 comments on commit 9e660ac

Please sign in to comment.