forked from mirrors/linux
		
	blk-iocost: don't release 'ioc->lock' while updating params
ioc_qos_write() and ioc_cost_model_write() are the same: 1) hold lock to read 'ioc->params' to local variable; 2) update params to local variable without lock; 3) hold lock to write local variable to 'ioc->params'; In theroy, if user updates params concurrenty, the params might be lost: t1: update params a t2: update params b spin_lock_irq(&ioc->lock); memcpy(qos, ioc->params.qos, sizeof(qos)) spin_unlock_irq(&ioc->lock); qos[a] = xxx; spin_lock_irq(&ioc->lock); memcpy(qos, ioc->params.qos, sizeof(qos)) spin_unlock_irq(&ioc->lock); qos[b] = xxx; spin_lock_irq(&ioc->lock); memcpy(ioc->params.qos, qos, sizeof(qos)); ioc_refresh_params(ioc, true); spin_unlock_irq(&ioc->lock); spin_lock_irq(&ioc->lock); // updates of a will be lost memcpy(ioc->params.qos, qos, sizeof(qos)); ioc_refresh_params(ioc, true); spin_unlock_irq(&ioc->lock); Althrough this is not common case, the problem can by fixed easily by holding the lock through the read, update, write process. Signed-off-by: Yu Kuai <yukuai3@huawei.com> Acked-by: Tejun Heo <tj@kernel.org> Link: https://lore.kernel.org/r/20221012094035.390056-3-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
		
							parent
							
								
									8796acbc9a
								
							
						
					
					
						commit
						2c06479884
					
				
					 1 changed files with 2 additions and 5 deletions
				
			
		|  | @ -3191,7 +3191,6 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, | ||||||
| 	memcpy(qos, ioc->params.qos, sizeof(qos)); | 	memcpy(qos, ioc->params.qos, sizeof(qos)); | ||||||
| 	enable = ioc->enabled; | 	enable = ioc->enabled; | ||||||
| 	user = ioc->user_qos_params; | 	user = ioc->user_qos_params; | ||||||
| 	spin_unlock_irq(&ioc->lock); |  | ||||||
| 
 | 
 | ||||||
| 	while ((p = strsep(&input, " \t\n"))) { | 	while ((p = strsep(&input, " \t\n"))) { | ||||||
| 		substring_t args[MAX_OPT_ARGS]; | 		substring_t args[MAX_OPT_ARGS]; | ||||||
|  | @ -3258,8 +3257,6 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, | ||||||
| 	if (qos[QOS_MIN] > qos[QOS_MAX]) | 	if (qos[QOS_MIN] > qos[QOS_MAX]) | ||||||
| 		goto einval; | 		goto einval; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irq(&ioc->lock); |  | ||||||
| 
 |  | ||||||
| 	if (enable) { | 	if (enable) { | ||||||
| 		blk_stat_enable_accounting(disk->queue); | 		blk_stat_enable_accounting(disk->queue); | ||||||
| 		blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); | 		blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); | ||||||
|  | @ -3284,6 +3281,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, | ||||||
| 	blkdev_put_no_open(bdev); | 	blkdev_put_no_open(bdev); | ||||||
| 	return nbytes; | 	return nbytes; | ||||||
| einval: | einval: | ||||||
|  | 	spin_unlock_irq(&ioc->lock); | ||||||
| 	ret = -EINVAL; | 	ret = -EINVAL; | ||||||
| err: | err: | ||||||
| 	blkdev_put_no_open(bdev); | 	blkdev_put_no_open(bdev); | ||||||
|  | @ -3359,7 +3357,6 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input, | ||||||
| 	spin_lock_irq(&ioc->lock); | 	spin_lock_irq(&ioc->lock); | ||||||
| 	memcpy(u, ioc->params.i_lcoefs, sizeof(u)); | 	memcpy(u, ioc->params.i_lcoefs, sizeof(u)); | ||||||
| 	user = ioc->user_cost_model; | 	user = ioc->user_cost_model; | ||||||
| 	spin_unlock_irq(&ioc->lock); |  | ||||||
| 
 | 
 | ||||||
| 	while ((p = strsep(&input, " \t\n"))) { | 	while ((p = strsep(&input, " \t\n"))) { | ||||||
| 		substring_t args[MAX_OPT_ARGS]; | 		substring_t args[MAX_OPT_ARGS]; | ||||||
|  | @ -3396,7 +3393,6 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input, | ||||||
| 		user = true; | 		user = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irq(&ioc->lock); |  | ||||||
| 	if (user) { | 	if (user) { | ||||||
| 		memcpy(ioc->params.i_lcoefs, u, sizeof(u)); | 		memcpy(ioc->params.i_lcoefs, u, sizeof(u)); | ||||||
| 		ioc->user_cost_model = true; | 		ioc->user_cost_model = true; | ||||||
|  | @ -3410,6 +3406,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input, | ||||||
| 	return nbytes; | 	return nbytes; | ||||||
| 
 | 
 | ||||||
| einval: | einval: | ||||||
|  | 	spin_unlock_irq(&ioc->lock); | ||||||
| 	ret = -EINVAL; | 	ret = -EINVAL; | ||||||
| err: | err: | ||||||
| 	blkdev_put_no_open(bdev); | 	blkdev_put_no_open(bdev); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Yu Kuai
						Yu Kuai