diff options
| author | Vivek Goyal <vgoyal@redhat.com> | 2010-10-01 21:16:42 +0200 | 
|---|---|---|
| committer | Jens Axboe <jaxboe@fusionio.com> | 2010-10-01 21:16:42 +0200 | 
| commit | c49c06e4960949a9bced708858433fcf6ca36a9c (patch) | |
| tree | 071c65544a98b6b0b599896591855f8ac69ab79a /block | |
| parent | 9355aede5a3c4975e0ba8bbfe2b9d1fd73308916 (diff) | |
blkio-throttle: Fix possible multiplication overflow in iops calculations
o User can specify max iops value of 32bit (UINT_MAX), through cgroup
  interface. If a user has specified say 4294967294 (UNIT_MAX  - 2), then
  on 32bit platform, following multiplication can overflow.
  io_allowed = (tg->iops[rw] * jiffy_elapsed_rnd)
o Explicitly cast the multiplication to 64bit and then perform division and
  then check whether result is still great then UNINT_MAX.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'block')
| -rw-r--r-- | block/blk-throttle.c | 16 | 
1 files changed, 15 insertions, 1 deletions
| diff --git a/block/blk-throttle.c b/block/blk-throttle.c index c1bc1b6c887a..56ad4531b412 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -430,6 +430,7 @@ static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg,  	bool rw = bio_data_dir(bio);  	unsigned int io_allowed;  	unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd; +	u64 tmp;  	jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw]; @@ -439,7 +440,20 @@ static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg,  	jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, throtl_slice); -	io_allowed = (tg->iops[rw] * jiffy_elapsed_rnd) / HZ; +	/* +	 * jiffy_elapsed_rnd should not be a big value as minimum iops can be +	 * 1 then at max jiffy elapsed should be equivalent of 1 second as we +	 * will allow dispatch after 1 second and after that slice should +	 * have been trimmed. +	 */ + +	tmp = (u64)tg->iops[rw] * jiffy_elapsed_rnd; +	do_div(tmp, HZ); + +	if (tmp > UINT_MAX) +		io_allowed = UINT_MAX; +	else +		io_allowed = tmp;  	if (tg->io_disp[rw] + 1 <= io_allowed) {  		if (wait) | 
