mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	bcache: fix inaccurate io state for detached bcache devices
When we run IO in a detached device,  and run iostat to shows IO status,
normally it will show like bellow (Omitted some fields):
Device: ... avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdd        ... 15.89     0.53    1.82    0.20    2.23   1.81  52.30
bcache0    ... 15.89   115.42    0.00    0.00    0.00   2.40  69.60
but after IO stopped, there are still very big avgqu-sz and %util
values as bellow:
Device: ... avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
bcache0   ...      0   5326.32    0.00    0.00    0.00   0.00 100.10
The reason for this issue is that, only generic_start_io_acct() called
and no generic_end_io_acct() called for detached device in
cached_dev_make_request(). See the code:
//start generic_start_io_acct()
generic_start_io_acct(q, rw, bio_sectors(bio), &d->disk->part0);
if (cached_dev_get(dc)) {
	//will callback generic_end_io_acct()
}
else {
	//will not call generic_end_io_acct()
}
This patch calls generic_end_io_acct() in the end of IO for detached
devices, so we can show IO state correctly.
(Modified to use GFP_NOIO in kzalloc() by Coly Li)
Changelog:
v2: fix typo.
v1: the initial version.
Signed-off-by: Tang Junhui <tang.junhui@zte.com.cn>
Reviewed-by: Coly Li <colyli@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Michael Lyle <mlyle@lyle.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
			
			
This commit is contained in:
		
							parent
							
								
									7e027ca4b5
								
							
						
					
					
						commit
						bc082a55d2
					
				| @ -986,6 +986,55 @@ static void cached_dev_nodata(struct closure *cl) | ||||
| 	continue_at(cl, cached_dev_bio_complete, NULL); | ||||
| } | ||||
| 
 | ||||
| struct detached_dev_io_private { | ||||
| 	struct bcache_device	*d; | ||||
| 	unsigned long		start_time; | ||||
| 	bio_end_io_t		*bi_end_io; | ||||
| 	void			*bi_private; | ||||
| }; | ||||
| 
 | ||||
| static void detached_dev_end_io(struct bio *bio) | ||||
| { | ||||
| 	struct detached_dev_io_private *ddip; | ||||
| 
 | ||||
| 	ddip = bio->bi_private; | ||||
| 	bio->bi_end_io = ddip->bi_end_io; | ||||
| 	bio->bi_private = ddip->bi_private; | ||||
| 
 | ||||
| 	generic_end_io_acct(ddip->d->disk->queue, | ||||
| 			    bio_data_dir(bio), | ||||
| 			    &ddip->d->disk->part0, ddip->start_time); | ||||
| 
 | ||||
| 	kfree(ddip); | ||||
| 
 | ||||
| 	bio->bi_end_io(bio); | ||||
| } | ||||
| 
 | ||||
| static void detached_dev_do_request(struct bcache_device *d, struct bio *bio) | ||||
| { | ||||
| 	struct detached_dev_io_private *ddip; | ||||
| 	struct cached_dev *dc = container_of(d, struct cached_dev, disk); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * no need to call closure_get(&dc->disk.cl), | ||||
| 	 * because upper layer had already opened bcache device, | ||||
| 	 * which would call closure_get(&dc->disk.cl) | ||||
| 	 */ | ||||
| 	ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO); | ||||
| 	ddip->d = d; | ||||
| 	ddip->start_time = jiffies; | ||||
| 	ddip->bi_end_io = bio->bi_end_io; | ||||
| 	ddip->bi_private = bio->bi_private; | ||||
| 	bio->bi_end_io = detached_dev_end_io; | ||||
| 	bio->bi_private = ddip; | ||||
| 
 | ||||
| 	if ((bio_op(bio) == REQ_OP_DISCARD) && | ||||
| 	    !blk_queue_discard(bdev_get_queue(dc->bdev))) | ||||
| 		bio->bi_end_io(bio); | ||||
| 	else | ||||
| 		generic_make_request(bio); | ||||
| } | ||||
| 
 | ||||
| /* Cached devices - read & write stuff */ | ||||
| 
 | ||||
| static blk_qc_t cached_dev_make_request(struct request_queue *q, | ||||
| @ -1028,13 +1077,8 @@ static blk_qc_t cached_dev_make_request(struct request_queue *q, | ||||
| 			else | ||||
| 				cached_dev_read(dc, s); | ||||
| 		} | ||||
| 	} else { | ||||
| 		if ((bio_op(bio) == REQ_OP_DISCARD) && | ||||
| 		    !blk_queue_discard(bdev_get_queue(dc->bdev))) | ||||
| 			bio_endio(bio); | ||||
| 		else | ||||
| 			generic_make_request(bio); | ||||
| 	} | ||||
| 	} else | ||||
| 		detached_dev_do_request(d, bio); | ||||
| 
 | ||||
| 	return BLK_QC_T_NONE; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Tang Junhui
						Tang Junhui