Commit d1ae8ffdfaa16b2ab2e9346e81cf0ab6eaaae347
Committed by
Jens Axboe
1 parent
5478755616
Exists in
master
and in
39 other branches
blk-throttle: Trim/adjust slice_end once a bio has been dispatched
o During some testing I did following and noticed throttling stops working. - Put a very low limit on a cgroup, say 1 byte per second. - Start some reads, this will set slice_end to a very high value. - Change the limit to higher value say 1MB/s - Now IO unthrottles and finishes as expected. - Try to do the read again but IO is not limited to 1MB/s as expected. o What is happening. - Initially low value of limit sets slice_end to a very high value. - During updation of limit, slice_end is not being truncated. - Very high value of slice_end leads to keeping the existing slice valid for a very long time and new slice does not start. - tg_may_dispatch() is called in blk_throtle_bio(), and trim_slice() is not called in this path. So slice_start is some old value and practically we are able to do huge amount of IO. o There are many ways it can be fixed. I have fixed it by trying to adjust/cleanup slice_end in trim_slice(). Generally we extend slices if bio is big and can't be dispatched in one slice. After dispatch of bio, readjust the slice_end to make sure we don't end up with huge values. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Showing 1 changed file with 16 additions and 0 deletions Side-by-side Diff
block/blk-throttle.c
... | ... | @@ -355,6 +355,12 @@ |
355 | 355 | tg->slice_end[rw], jiffies); |
356 | 356 | } |
357 | 357 | |
358 | +static inline void throtl_set_slice_end(struct throtl_data *td, | |
359 | + struct throtl_grp *tg, bool rw, unsigned long jiffy_end) | |
360 | +{ | |
361 | + tg->slice_end[rw] = roundup(jiffy_end, throtl_slice); | |
362 | +} | |
363 | + | |
358 | 364 | static inline void throtl_extend_slice(struct throtl_data *td, |
359 | 365 | struct throtl_grp *tg, bool rw, unsigned long jiffy_end) |
360 | 366 | { |
... | ... | @@ -390,6 +396,16 @@ |
390 | 396 | */ |
391 | 397 | if (throtl_slice_used(td, tg, rw)) |
392 | 398 | return; |
399 | + | |
400 | + /* | |
401 | + * A bio has been dispatched. Also adjust slice_end. It might happen | |
402 | + * that initially cgroup limit was very low resulting in high | |
403 | + * slice_end, but later limit was bumped up and bio was dispached | |
404 | + * sooner, then we need to reduce slice_end. A high bogus slice_end | |
405 | + * is bad because it does not allow new slice to start. | |
406 | + */ | |
407 | + | |
408 | + throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice); | |
393 | 409 | |
394 | 410 | time_elapsed = jiffies - tg->slice_start[rw]; |
395 | 411 |