linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH -next 0/5] blk-iocost: random patches to improve configuration
@ 2022-10-28 10:10 Yu Kuai
  2022-10-28 10:10 ` [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write() Yu Kuai
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Yu Kuai @ 2022-10-28 10:10 UTC (permalink / raw)
  To: tj, josef, axboe, yukuai3
  Cc: cgroups, linux-block, linux-kernel, yukuai1, yi.zhang

From: Yu Kuai <yukuai3@huawei.com>

Yu Kuai (5):
  blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write()
  blk-iocost: improve hanlder of match_u64()
  blk-iocost: don't allow to configure bio based device
  blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write()
  blk-iocost: fix sleeping in atomic context warnning in
    ioc_cost_model_write()

 block/blk-iocost.c | 328 +++++++++++++++++++++++++++++----------------
 1 file changed, 216 insertions(+), 112 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write()
  2022-10-28 10:10 [PATCH -next 0/5] blk-iocost: random patches to improve configuration Yu Kuai
@ 2022-10-28 10:10 ` Yu Kuai
  2022-10-30  9:40   ` Christoph Hellwig
  2022-10-28 10:10 ` [PATCH -next 2/5] blk-iocost: improve hanlder of match_u64() Yu Kuai
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Yu Kuai @ 2022-10-28 10:10 UTC (permalink / raw)
  To: tj, josef, axboe, yukuai3
  Cc: cgroups, linux-block, linux-kernel, yukuai1, yi.zhang

From: Yu Kuai <yukuai3@huawei.com>

There are no functional changes, just to make the code a litter cleaner
and follow up patches easier.

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
 block/blk-iocost.c | 62 +++++++++++++++++++---------------------------
 1 file changed, 25 insertions(+), 37 deletions(-)

diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index f01359906c83..fd495e823db2 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3185,7 +3185,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 	if (!ioc) {
 		ret = blk_iocost_init(disk);
 		if (ret)
-			goto err;
+			goto out;
 		ioc = q_to_ioc(disk->queue);
 	}
 
@@ -3197,6 +3197,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 	enable = ioc->enabled;
 	user = ioc->user_qos_params;
 
+	ret = -EINVAL;
 	while ((p = strsep(&input, " \t\n"))) {
 		substring_t args[MAX_OPT_ARGS];
 		char buf[32];
@@ -3218,7 +3219,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 			else if (!strcmp(buf, "user"))
 				user = true;
 			else
-				goto einval;
+				goto out_unlock;
 			continue;
 		}
 
@@ -3228,39 +3229,39 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 		case QOS_WPPM:
 			if (match_strlcpy(buf, &args[0], sizeof(buf)) >=
 			    sizeof(buf))
-				goto einval;
+				goto out_unlock;
 			if (cgroup_parse_float(buf, 2, &v))
-				goto einval;
+				goto out_unlock;
 			if (v < 0 || v > 10000)
-				goto einval;
+				goto out_unlock;
 			qos[tok] = v * 100;
 			break;
 		case QOS_RLAT:
 		case QOS_WLAT:
 			if (match_u64(&args[0], &v))
-				goto einval;
+				goto out_unlock;
 			qos[tok] = v;
 			break;
 		case QOS_MIN:
 		case QOS_MAX:
 			if (match_strlcpy(buf, &args[0], sizeof(buf)) >=
 			    sizeof(buf))
-				goto einval;
+				goto out_unlock;
 			if (cgroup_parse_float(buf, 2, &v))
-				goto einval;
+				goto out_unlock;
 			if (v < 0)
-				goto einval;
+				goto out_unlock;
 			qos[tok] = clamp_t(s64, v * 100,
 					   VRATE_MIN_PPM, VRATE_MAX_PPM);
 			break;
 		default:
-			goto einval;
+			goto out_unlock;
 		}
 		user = true;
 	}
 
 	if (qos[QOS_MIN] > qos[QOS_MAX])
-		goto einval;
+		goto out_unlock;
 
 	if (enable) {
 		blk_stat_enable_accounting(disk->queue);
@@ -3281,21 +3282,14 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 	}
 
 	ioc_refresh_params(ioc, true);
-	spin_unlock_irq(&ioc->lock);
+	ret = nbytes;
 
-	blk_mq_unquiesce_queue(disk->queue);
-	blk_mq_unfreeze_queue(disk->queue);
-
-	blkdev_put_no_open(bdev);
-	return nbytes;
-einval:
+out_unlock:
 	spin_unlock_irq(&ioc->lock);
-
 	blk_mq_unquiesce_queue(disk->queue);
 	blk_mq_unfreeze_queue(disk->queue);
 
-	ret = -EINVAL;
-err:
+out:
 	blkdev_put_no_open(bdev);
 	return ret;
 }
@@ -3364,7 +3358,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 	if (!ioc) {
 		ret = blk_iocost_init(bdev->bd_disk);
 		if (ret)
-			goto err;
+			goto out;
 		ioc = q_to_ioc(q);
 	}
 
@@ -3375,6 +3369,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 	memcpy(u, ioc->params.i_lcoefs, sizeof(u));
 	user = ioc->user_cost_model;
 
+	ret = -EINVAL;
 	while ((p = strsep(&input, " \t\n"))) {
 		substring_t args[MAX_OPT_ARGS];
 		char buf[32];
@@ -3392,20 +3387,20 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 			else if (!strcmp(buf, "user"))
 				user = true;
 			else
-				goto einval;
+				goto out_unlock;
 			continue;
 		case COST_MODEL:
 			match_strlcpy(buf, &args[0], sizeof(buf));
 			if (strcmp(buf, "linear"))
-				goto einval;
+				goto out_unlock;
 			continue;
 		}
 
 		tok = match_token(p, i_lcoef_tokens, args);
 		if (tok == NR_I_LCOEFS)
-			goto einval;
+			goto out_unlock;
 		if (match_u64(&args[0], &v))
-			goto einval;
+			goto out_unlock;
 		u[tok] = v;
 		user = true;
 	}
@@ -3416,23 +3411,16 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 	} else {
 		ioc->user_cost_model = false;
 	}
-	ioc_refresh_params(ioc, true);
-	spin_unlock_irq(&ioc->lock);
 
-	blk_mq_unquiesce_queue(q);
-	blk_mq_unfreeze_queue(q);
-
-	blkdev_put_no_open(bdev);
-	return nbytes;
+	ioc_refresh_params(ioc, true);
+	ret = nbytes;
 
-einval:
+out_unlock:
 	spin_unlock_irq(&ioc->lock);
-
 	blk_mq_unquiesce_queue(q);
 	blk_mq_unfreeze_queue(q);
 
-	ret = -EINVAL;
-err:
+out:
 	blkdev_put_no_open(bdev);
 	return ret;
 }
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 2/5] blk-iocost: improve hanlder of match_u64()
  2022-10-28 10:10 [PATCH -next 0/5] blk-iocost: random patches to improve configuration Yu Kuai
  2022-10-28 10:10 ` [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write() Yu Kuai
@ 2022-10-28 10:10 ` Yu Kuai
  2022-10-30  9:40   ` Christoph Hellwig
  2022-10-28 10:10 ` [PATCH -next 3/5] blk-iocost: don't allow to configure bio based device Yu Kuai
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Yu Kuai @ 2022-10-28 10:10 UTC (permalink / raw)
  To: tj, josef, axboe, yukuai3
  Cc: cgroups, linux-block, linux-kernel, yukuai1, yi.zhang

From: Yu Kuai <yukuai3@huawei.com>

1) There are one place that return value of match_u64() is not checked.
2) If match_u64() failed, return value is set to -EINVAL despite that
   there are other possible errnos.

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
 block/blk-iocost.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index fd495e823db2..c532129a1456 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3202,6 +3202,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 		substring_t args[MAX_OPT_ARGS];
 		char buf[32];
 		int tok;
+		int err;
 		s64 v;
 
 		if (!*p)
@@ -3209,7 +3210,12 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 
 		switch (match_token(p, qos_ctrl_tokens, args)) {
 		case QOS_ENABLE:
-			match_u64(&args[0], &v);
+			err = match_u64(&args[0], &v);
+			if (err) {
+				ret = err;
+				goto out_unlock;
+			}
+
 			enable = v;
 			continue;
 		case QOS_CTRL:
@@ -3238,8 +3244,12 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 			break;
 		case QOS_RLAT:
 		case QOS_WLAT:
-			if (match_u64(&args[0], &v))
+			err = match_u64(&args[0], &v);
+			if (err) {
+				ret = err;
 				goto out_unlock;
+			}
+
 			qos[tok] = v;
 			break;
 		case QOS_MIN:
@@ -3374,6 +3384,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 		substring_t args[MAX_OPT_ARGS];
 		char buf[32];
 		int tok;
+		int err;
 		u64 v;
 
 		if (!*p)
@@ -3399,8 +3410,13 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 		tok = match_token(p, i_lcoef_tokens, args);
 		if (tok == NR_I_LCOEFS)
 			goto out_unlock;
-		if (match_u64(&args[0], &v))
+
+		err = match_u64(&args[0], &v);
+		if (err) {
+			ret = err;
 			goto out_unlock;
+		}
+
 		u[tok] = v;
 		user = true;
 	}
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 3/5] blk-iocost: don't allow to configure bio based device
  2022-10-28 10:10 [PATCH -next 0/5] blk-iocost: random patches to improve configuration Yu Kuai
  2022-10-28 10:10 ` [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write() Yu Kuai
  2022-10-28 10:10 ` [PATCH -next 2/5] blk-iocost: improve hanlder of match_u64() Yu Kuai
@ 2022-10-28 10:10 ` Yu Kuai
  2022-10-30  9:41   ` Christoph Hellwig
  2022-10-28 10:10 ` [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write() Yu Kuai
  2022-10-28 10:10 ` [PATCH -next 5/5] blk-iocost: fix sleeping in atomic context warnning in ioc_cost_model_write() Yu Kuai
  4 siblings, 1 reply; 11+ messages in thread
From: Yu Kuai @ 2022-10-28 10:10 UTC (permalink / raw)
  To: tj, josef, axboe, yukuai3
  Cc: cgroups, linux-block, linux-kernel, yukuai1, yi.zhang

From: Yu Kuai <yukuai3@huawei.com>

iocost is based on rq_qos, which can only work for request based device,
thus it doesn't make sense to configure iocost for bio based device.

Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
 block/blk-iocost.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index c532129a1456..2bfecc511dd9 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3181,6 +3181,11 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 		return PTR_ERR(bdev);
 
 	disk = bdev->bd_disk;
+	if (!queue_is_mq(disk->queue)) {
+		ret = -EPERM;
+		goto out;
+	}
+
 	ioc = q_to_ioc(disk->queue);
 	if (!ioc) {
 		ret = blk_iocost_init(disk);
@@ -3364,6 +3369,11 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 		return PTR_ERR(bdev);
 
 	q = bdev_get_queue(bdev);
+	if (!queue_is_mq(q)) {
+		ret = -EPERM;
+		goto out;
+	}
+
 	ioc = q_to_ioc(q);
 	if (!ioc) {
 		ret = blk_iocost_init(bdev->bd_disk);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write()
  2022-10-28 10:10 [PATCH -next 0/5] blk-iocost: random patches to improve configuration Yu Kuai
                   ` (2 preceding siblings ...)
  2022-10-28 10:10 ` [PATCH -next 3/5] blk-iocost: don't allow to configure bio based device Yu Kuai
@ 2022-10-28 10:10 ` Yu Kuai
  2022-10-30  9:55   ` Christoph Hellwig
  2022-10-28 10:10 ` [PATCH -next 5/5] blk-iocost: fix sleeping in atomic context warnning in ioc_cost_model_write() Yu Kuai
  4 siblings, 1 reply; 11+ messages in thread
From: Yu Kuai @ 2022-10-28 10:10 UTC (permalink / raw)
  To: tj, josef, axboe, yukuai3
  Cc: cgroups, linux-block, linux-kernel, yukuai1, yi.zhang

From: Yu Kuai <yukuai3@huawei.com>

match_u64() is called inside ioc->lock, which causes smatch static
checker warnings:

block/blk-iocost.c:3211 ioc_qos_write() warn: sleeping in atomic context
block/blk-iocost.c:3240 ioc_qos_write() warn: sleeping in atomic context

Fix the problem by prase params before holding the lock.

Fixes: 2c0647988433 ("blk-iocost: don't release 'ioc->lock' while updating params")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
 block/blk-iocost.c | 172 +++++++++++++++++++++++++++++----------------
 1 file changed, 111 insertions(+), 61 deletions(-)

diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 2bfecc511dd9..27b41f3f1b07 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3165,44 +3165,25 @@ static const match_table_t qos_tokens = {
 	{ NR_QOS_PARAMS,	NULL		},
 };
 
-static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
-			     size_t nbytes, loff_t off)
-{
-	struct block_device *bdev;
-	struct gendisk *disk;
-	struct ioc *ioc;
+struct ioc_qos_params {
 	u32 qos[NR_QOS_PARAMS];
-	bool enable, user;
-	char *p;
-	int ret;
-
-	bdev = blkcg_conf_open_bdev(&input);
-	if (IS_ERR(bdev))
-		return PTR_ERR(bdev);
-
-	disk = bdev->bd_disk;
-	if (!queue_is_mq(disk->queue)) {
-		ret = -EPERM;
-		goto out;
-	}
-
-	ioc = q_to_ioc(disk->queue);
-	if (!ioc) {
-		ret = blk_iocost_init(disk);
-		if (ret)
-			goto out;
-		ioc = q_to_ioc(disk->queue);
-	}
+	bool enable;
+	bool user;
+	bool set_qos[NR_QOS_PARAMS];
+	bool set_enable;
+	bool set_user;
+};
 
-	blk_mq_freeze_queue(disk->queue);
-	blk_mq_quiesce_queue(disk->queue);
+static struct ioc_qos_params *ioc_qos_parse_params(char *input)
+{
+	struct ioc_qos_params *params;
+	char *p;
+	int ret = -EINVAL;
 
-	spin_lock_irq(&ioc->lock);
-	memcpy(qos, ioc->params.qos, sizeof(qos));
-	enable = ioc->enabled;
-	user = ioc->user_qos_params;
+	params = kzalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return ERR_PTR(-ENOMEM);
 
-	ret = -EINVAL;
 	while ((p = strsep(&input, " \t\n"))) {
 		substring_t args[MAX_OPT_ARGS];
 		char buf[32];
@@ -3218,19 +3199,21 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 			err = match_u64(&args[0], &v);
 			if (err) {
 				ret = err;
-				goto out_unlock;
+				goto out_err;
 			}
 
-			enable = v;
+			params->enable = v;
+			params->set_enable = true;
 			continue;
 		case QOS_CTRL:
 			match_strlcpy(buf, &args[0], sizeof(buf));
 			if (!strcmp(buf, "auto"))
-				user = false;
+				params->user = false;
 			else if (!strcmp(buf, "user"))
-				user = true;
+				params->user = true;
 			else
-				goto out_unlock;
+				goto out_err;
+			params->set_user = true;
 			continue;
 		}
 
@@ -3240,62 +3223,128 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 		case QOS_WPPM:
 			if (match_strlcpy(buf, &args[0], sizeof(buf)) >=
 			    sizeof(buf))
-				goto out_unlock;
+				goto out_err;
 			if (cgroup_parse_float(buf, 2, &v))
-				goto out_unlock;
+				goto out_err;
 			if (v < 0 || v > 10000)
-				goto out_unlock;
-			qos[tok] = v * 100;
+				goto out_err;
+			params->qos[tok] = v * 100;
 			break;
 		case QOS_RLAT:
 		case QOS_WLAT:
 			err = match_u64(&args[0], &v);
 			if (err) {
 				ret = err;
-				goto out_unlock;
+				goto out_err;
 			}
 
-			qos[tok] = v;
+			params->qos[tok] = v;
 			break;
 		case QOS_MIN:
 		case QOS_MAX:
 			if (match_strlcpy(buf, &args[0], sizeof(buf)) >=
 			    sizeof(buf))
-				goto out_unlock;
+				goto out_err;
 			if (cgroup_parse_float(buf, 2, &v))
-				goto out_unlock;
+				goto out_err;
 			if (v < 0)
-				goto out_unlock;
-			qos[tok] = clamp_t(s64, v * 100,
+				goto out_err;
+			params->qos[tok] = clamp_t(s64, v * 100,
 					   VRATE_MIN_PPM, VRATE_MAX_PPM);
 			break;
 		default:
-			goto out_unlock;
+			goto out_err;
 		}
-		user = true;
+		params->user = true;
+		params->set_user = true;
+		params->set_qos[tok] = true;
 	}
 
-	if (qos[QOS_MIN] > qos[QOS_MAX])
-		goto out_unlock;
+	return params;
+
+out_err:
+	kfree(params);
+	return ERR_PTR(ret);
+}
+
+static int ioc_qos_update_params(struct request_queue *q, struct ioc *ioc,
+				 struct ioc_qos_params *params)
+{
+	int i;
 
-	if (enable) {
-		blk_stat_enable_accounting(disk->queue);
-		blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
+	for (i = 0; i < NR_QOS_PARAMS; ++i)
+		if (!params->set_qos[i])
+			params->qos[i] = ioc->params.qos[i];
+	if (params->qos[QOS_MIN] > params->qos[QOS_MAX])
+		return -EINVAL;
+
+	if (!params->set_enable)
+		params->enable = ioc->enabled;
+	if (params->enable) {
+		blk_stat_enable_accounting(q);
+		blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, q);
 		ioc->enabled = true;
-		wbt_disable_default(disk->queue);
+		wbt_disable_default(q);
 	} else {
-		blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
+		blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, q);
 		ioc->enabled = false;
-		wbt_enable_default(disk->queue);
+		wbt_enable_default(q);
 	}
 
-	if (user) {
-		memcpy(ioc->params.qos, qos, sizeof(qos));
+	if (!params->set_user)
+		params->user = ioc->user_qos_params;
+	if (params->user) {
+		memcpy(ioc->params.qos, params->qos, sizeof(params->qos));
 		ioc->user_qos_params = true;
 	} else {
 		ioc->user_qos_params = false;
 	}
 
+	return 0;
+}
+
+static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
+			     size_t nbytes, loff_t off)
+{
+	struct block_device *bdev;
+	struct gendisk *disk;
+	struct ioc *ioc;
+	struct ioc_qos_params *params;
+	int ret;
+
+	bdev = blkcg_conf_open_bdev(&input);
+	if (IS_ERR(bdev))
+		return PTR_ERR(bdev);
+
+	disk = bdev->bd_disk;
+	if (!queue_is_mq(disk->queue)) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	ioc = q_to_ioc(disk->queue);
+	if (!ioc) {
+		ret = blk_iocost_init(disk);
+		if (ret)
+			goto out;
+		ioc = q_to_ioc(disk->queue);
+	}
+
+	params = ioc_qos_parse_params(input);
+	if (IS_ERR(params)) {
+		ret = PTR_ERR(params);
+		goto out;
+	}
+
+	blk_mq_freeze_queue(disk->queue);
+	blk_mq_quiesce_queue(disk->queue);
+
+	spin_lock_irq(&ioc->lock);
+
+	ret = ioc_qos_update_params(disk->queue, ioc, params);
+	if (ret)
+		goto out_unlock;
+
 	ioc_refresh_params(ioc, true);
 	ret = nbytes;
 
@@ -3303,6 +3352,7 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
 	spin_unlock_irq(&ioc->lock);
 	blk_mq_unquiesce_queue(disk->queue);
 	blk_mq_unfreeze_queue(disk->queue);
+	kfree(params);
 
 out:
 	blkdev_put_no_open(bdev);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH -next 5/5] blk-iocost: fix sleeping in atomic context warnning in ioc_cost_model_write()
  2022-10-28 10:10 [PATCH -next 0/5] blk-iocost: random patches to improve configuration Yu Kuai
                   ` (3 preceding siblings ...)
  2022-10-28 10:10 ` [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write() Yu Kuai
@ 2022-10-28 10:10 ` Yu Kuai
  4 siblings, 0 replies; 11+ messages in thread
From: Yu Kuai @ 2022-10-28 10:10 UTC (permalink / raw)
  To: tj, josef, axboe, yukuai3
  Cc: cgroups, linux-block, linux-kernel, yukuai1, yi.zhang

From: Yu Kuai <yukuai3@huawei.com>

match_u64() is called inside ioc->lock, which causes smatch static
checker warnings:

block/blk-iocost.c:3407 ioc_cost_model_write() warn: sleeping in atomic context

Fix the problem by prase params before holding the lock.

Fixes: 2c0647988433 ("blk-iocost: don't release 'ioc->lock' while updating params")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
---
 block/blk-iocost.c | 128 +++++++++++++++++++++++++++++----------------
 1 file changed, 84 insertions(+), 44 deletions(-)

diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 27b41f3f1b07..62e18c2719cb 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3403,43 +3403,23 @@ static const match_table_t i_lcoef_tokens = {
 	{ NR_I_LCOEFS,		NULL		},
 };
 
-static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
-				    size_t nbytes, loff_t off)
-{
-	struct block_device *bdev;
-	struct request_queue *q;
-	struct ioc *ioc;
+struct ioc_model_params {
 	u64 u[NR_I_LCOEFS];
 	bool user;
-	char *p;
-	int ret;
-
-	bdev = blkcg_conf_open_bdev(&input);
-	if (IS_ERR(bdev))
-		return PTR_ERR(bdev);
-
-	q = bdev_get_queue(bdev);
-	if (!queue_is_mq(q)) {
-		ret = -EPERM;
-		goto out;
-	}
-
-	ioc = q_to_ioc(q);
-	if (!ioc) {
-		ret = blk_iocost_init(bdev->bd_disk);
-		if (ret)
-			goto out;
-		ioc = q_to_ioc(q);
-	}
+	bool set_u[NR_I_LCOEFS];
+	bool set_user;
+};
 
-	blk_mq_freeze_queue(q);
-	blk_mq_quiesce_queue(q);
+static struct ioc_model_params *ioc_model_parse_params(char *input)
+{
+	struct ioc_model_params *params;
+	char *p;
+	int ret = -EINVAL;
 
-	spin_lock_irq(&ioc->lock);
-	memcpy(u, ioc->params.i_lcoefs, sizeof(u));
-	user = ioc->user_cost_model;
+	params = kzalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return ERR_PTR(-ENOMEM);
 
-	ret = -EINVAL;
 	while ((p = strsep(&input, " \t\n"))) {
 		substring_t args[MAX_OPT_ARGS];
 		char buf[32];
@@ -3454,48 +3434,108 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
 		case COST_CTRL:
 			match_strlcpy(buf, &args[0], sizeof(buf));
 			if (!strcmp(buf, "auto"))
-				user = false;
+				params->user = false;
 			else if (!strcmp(buf, "user"))
-				user = true;
+				params->user = true;
 			else
-				goto out_unlock;
+				goto err;
+			params->set_user = true;
 			continue;
 		case COST_MODEL:
 			match_strlcpy(buf, &args[0], sizeof(buf));
 			if (strcmp(buf, "linear"))
-				goto out_unlock;
+				goto err;
 			continue;
 		}
 
 		tok = match_token(p, i_lcoef_tokens, args);
 		if (tok == NR_I_LCOEFS)
-			goto out_unlock;
+			goto err;
 
 		err = match_u64(&args[0], &v);
 		if (err) {
 			ret = err;
-			goto out_unlock;
+			goto err;
 		}
 
-		u[tok] = v;
-		user = true;
+		params->u[tok] = v;
+		params->set_u[tok] = true;
+		params->user = true;
+		params->set_user = true;
 	}
 
-	if (user) {
-		memcpy(ioc->params.i_lcoefs, u, sizeof(u));
+	return params;
+
+err:
+	kfree(params);
+	return ERR_PTR(ret);
+}
+
+static void ioc_model_update_params(struct ioc *ioc,
+				    struct ioc_model_params *params)
+{
+	int i;
+
+	if (!params->set_user)
+		params->user = ioc->user_cost_model;
+	if (params->user) {
+		for (i = 0; i < NR_I_LCOEFS; ++i)
+			if (params->set_u[i])
+				ioc->params.i_lcoefs[i] = params->u[i];
 		ioc->user_cost_model = true;
 	} else {
 		ioc->user_cost_model = false;
 	}
+}
+
+static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
+				    size_t nbytes, loff_t off)
+{
+	struct block_device *bdev;
+	struct request_queue *q;
+	struct ioc *ioc;
+	struct ioc_model_params *params;
+	int ret;
+
+	bdev = blkcg_conf_open_bdev(&input);
+	if (IS_ERR(bdev))
+		return PTR_ERR(bdev);
+
+	q = bdev_get_queue(bdev);
+	if (!queue_is_mq(q)) {
+		ret = -EPERM;
+		goto out;
+	}
 
+	ioc = q_to_ioc(q);
+	if (!ioc) {
+		ret = blk_iocost_init(bdev->bd_disk);
+		if (ret)
+			goto out;
+		ioc = q_to_ioc(q);
+	}
+
+	params = ioc_model_parse_params(input);
+	if (IS_ERR(params)) {
+		ret = PTR_ERR(params);
+		goto out;
+	}
+
+	blk_mq_freeze_queue(q);
+	blk_mq_quiesce_queue(q);
+
+	spin_lock_irq(&ioc->lock);
+
+	ioc_model_update_params(ioc, params);
 	ioc_refresh_params(ioc, true);
-	ret = nbytes;
 
-out_unlock:
 	spin_unlock_irq(&ioc->lock);
+
 	blk_mq_unquiesce_queue(q);
 	blk_mq_unfreeze_queue(q);
 
+	kfree(params);
+	ret = nbytes;
 out:
 	blkdev_put_no_open(bdev);
 	return ret;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write()
  2022-10-28 10:10 ` [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write() Yu Kuai
@ 2022-10-30  9:40   ` Christoph Hellwig
  0 siblings, 0 replies; 11+ messages in thread
From: Christoph Hellwig @ 2022-10-30  9:40 UTC (permalink / raw)
  To: Yu Kuai
  Cc: tj, josef, axboe, yukuai3, cgroups, linux-block, linux-kernel,
	yi.zhang

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 2/5] blk-iocost: improve hanlder of match_u64()
  2022-10-28 10:10 ` [PATCH -next 2/5] blk-iocost: improve hanlder of match_u64() Yu Kuai
@ 2022-10-30  9:40   ` Christoph Hellwig
  0 siblings, 0 replies; 11+ messages in thread
From: Christoph Hellwig @ 2022-10-30  9:40 UTC (permalink / raw)
  To: Yu Kuai
  Cc: tj, josef, axboe, yukuai3, cgroups, linux-block, linux-kernel,
	yi.zhang

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 3/5] blk-iocost: don't allow to configure bio based device
  2022-10-28 10:10 ` [PATCH -next 3/5] blk-iocost: don't allow to configure bio based device Yu Kuai
@ 2022-10-30  9:41   ` Christoph Hellwig
  0 siblings, 0 replies; 11+ messages in thread
From: Christoph Hellwig @ 2022-10-30  9:41 UTC (permalink / raw)
  To: Yu Kuai
  Cc: tj, josef, axboe, yukuai3, cgroups, linux-block, linux-kernel,
	yi.zhang

Looks good (I actually stubled over this a few days ago as well):

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write()
  2022-10-28 10:10 ` [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write() Yu Kuai
@ 2022-10-30  9:55   ` Christoph Hellwig
  2022-10-31  1:33     ` Yu Kuai
  0 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2022-10-30  9:55 UTC (permalink / raw)
  To: Yu Kuai
  Cc: tj, josef, axboe, yukuai3, cgroups, linux-block, linux-kernel,
	yi.zhang

This seems a little convoluted to me.  I'd suggest to add a new
sleeping lock that protects the updates, then you just take the
spinlock after parsing without much other changes.

(The same comment also applies to patch 5).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write()
  2022-10-30  9:55   ` Christoph Hellwig
@ 2022-10-31  1:33     ` Yu Kuai
  0 siblings, 0 replies; 11+ messages in thread
From: Yu Kuai @ 2022-10-31  1:33 UTC (permalink / raw)
  To: Christoph Hellwig, Yu Kuai
  Cc: tj, josef, axboe, cgroups, linux-block, linux-kernel, yi.zhang,
	yukuai (C)

Hi,

在 2022/10/30 17:55, Christoph Hellwig 写道:
> This seems a little convoluted to me.  I'd suggest to add a new
> sleeping lock that protects the updates, then you just take the
> spinlock after parsing without much other changes.
> 
> (The same comment also applies to patch 5).

Yes, add a new sleeping lock is ok, and changes will be much simpler.

Thanks for the suggestion, I'll send a new verion soon.

Kuai
> .
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-10-31  1:33 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-28 10:10 [PATCH -next 0/5] blk-iocost: random patches to improve configuration Yu Kuai
2022-10-28 10:10 ` [PATCH -next 1/5] blk-iocost: cleanup ioc_qos_write() and ioc_cost_model_write() Yu Kuai
2022-10-30  9:40   ` Christoph Hellwig
2022-10-28 10:10 ` [PATCH -next 2/5] blk-iocost: improve hanlder of match_u64() Yu Kuai
2022-10-30  9:40   ` Christoph Hellwig
2022-10-28 10:10 ` [PATCH -next 3/5] blk-iocost: don't allow to configure bio based device Yu Kuai
2022-10-30  9:41   ` Christoph Hellwig
2022-10-28 10:10 ` [PATCH -next 4/5] blk-iocost: fix sleeping in atomic context warnning in ioc_qos_write() Yu Kuai
2022-10-30  9:55   ` Christoph Hellwig
2022-10-31  1:33     ` Yu Kuai
2022-10-28 10:10 ` [PATCH -next 5/5] blk-iocost: fix sleeping in atomic context warnning in ioc_cost_model_write() Yu Kuai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).