aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2015-08-18 17:55:31 -0400
committerJens Axboe <axboe@fb.com>2015-08-18 18:49:18 -0400
commit36aa9e5f591e84d67aad2c5bff75e413d77660dd (patch)
tree228d8986be70359b086c30a453d1fc7ee77cfada /block
parent880f50e228f80626dff6327a6e281e40286f5228 (diff)
blkcg: move body parsing from blkg_conf_prep() to its callers
Currently, blkg_conf_prep() expects input to be of the following form MAJ:MIN NUM and reads the NUM part into blkg_conf_ctx->v. This is quite restrictive and gets in the way in implementing blkcg interface for the unified hierarchy. This patch updates blkg_conf_prep() so that it expects MAJ:MIN BODY_STR where BODY_STR is an arbitrary string. blkg_conf_ctx->v is replaced with ->body which is a char pointer pointing to the start of BODY_STR. Parsing of the body is moved to blkg_conf_prep()'s callers. To allow using, for example, strsep() on blkg_conf_ctx->val, it is a non-const pointer and to accommodate that const is dropped from @input too. This doesn't cause any behavior changes. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-cgroup.c22
-rw-r--r--block/blk-throttle.c18
-rw-r--r--block/cfq-iosched.c17
3 files changed, 37 insertions, 20 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 429726bed560..8ee1ca4d4f2f 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -24,6 +24,7 @@
24#include <linux/genhd.h> 24#include <linux/genhd.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/atomic.h> 26#include <linux/atomic.h>
27#include <linux/ctype.h>
27#include <linux/blk-cgroup.h> 28#include <linux/blk-cgroup.h>
28#include "blk.h" 29#include "blk.h"
29 30
@@ -773,23 +774,28 @@ EXPORT_SYMBOL_GPL(blkg_rwstat_recursive_sum);
773 * @ctx: blkg_conf_ctx to be filled 774 * @ctx: blkg_conf_ctx to be filled
774 * 775 *
775 * Parse per-blkg config update from @input and initialize @ctx with the 776 * Parse per-blkg config update from @input and initialize @ctx with the
776 * result. @ctx->blkg points to the blkg to be updated and @ctx->v the new 777 * result. @ctx->blkg points to the blkg to be updated and @ctx->body the
777 * value. This function returns with RCU read lock and queue lock held and 778 * part of @input following MAJ:MIN. This function returns with RCU read
778 * must be paired with blkg_conf_finish(). 779 * lock and queue lock held and must be paired with blkg_conf_finish().
779 */ 780 */
780int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, 781int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
781 const char *input, struct blkg_conf_ctx *ctx) 782 char *input, struct blkg_conf_ctx *ctx)
782 __acquires(rcu) __acquires(disk->queue->queue_lock) 783 __acquires(rcu) __acquires(disk->queue->queue_lock)
783{ 784{
784 struct gendisk *disk; 785 struct gendisk *disk;
785 struct blkcg_gq *blkg; 786 struct blkcg_gq *blkg;
786 unsigned int major, minor; 787 unsigned int major, minor;
787 unsigned long long v; 788 int key_len, part, ret;
788 int part, ret; 789 char *body;
789 790
790 if (sscanf(input, "%u:%u %llu", &major, &minor, &v) != 3) 791 if (sscanf(input, "%u:%u%n", &major, &minor, &key_len) != 2)
791 return -EINVAL; 792 return -EINVAL;
792 793
794 body = input + key_len;
795 if (!isspace(*body))
796 return -EINVAL;
797 body = skip_spaces(body);
798
793 disk = get_gendisk(MKDEV(major, minor), &part); 799 disk = get_gendisk(MKDEV(major, minor), &part);
794 if (!disk) 800 if (!disk)
795 return -ENODEV; 801 return -ENODEV;
@@ -826,7 +832,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
826 832
827 ctx->disk = disk; 833 ctx->disk = disk;
828 ctx->blkg = blkg; 834 ctx->blkg = blkg;
829 ctx->v = v; 835 ctx->body = body;
830 return 0; 836 return 0;
831} 837}
832EXPORT_SYMBOL_GPL(blkg_conf_prep); 838EXPORT_SYMBOL_GPL(blkg_conf_prep);
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 8b4f6b81bb72..0e17c8f92d25 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1154,21 +1154,25 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
1154 struct blkcg_gq *blkg; 1154 struct blkcg_gq *blkg;
1155 struct cgroup_subsys_state *pos_css; 1155 struct cgroup_subsys_state *pos_css;
1156 int ret; 1156 int ret;
1157 u64 v;
1157 1158
1158 ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, buf, &ctx); 1159 ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, buf, &ctx);
1159 if (ret) 1160 if (ret)
1160 return ret; 1161 return ret;
1161 1162
1163 ret = -EINVAL;
1164 if (sscanf(ctx.body, "%llu", &v) != 1)
1165 goto out_finish;
1166 if (!v)
1167 v = -1;
1168
1162 tg = blkg_to_tg(ctx.blkg); 1169 tg = blkg_to_tg(ctx.blkg);
1163 sq = &tg->service_queue; 1170 sq = &tg->service_queue;
1164 1171
1165 if (!ctx.v)
1166 ctx.v = -1;
1167
1168 if (is_u64) 1172 if (is_u64)
1169 *(u64 *)((void *)tg + of_cft(of)->private) = ctx.v; 1173 *(u64 *)((void *)tg + of_cft(of)->private) = v;
1170 else 1174 else
1171 *(unsigned int *)((void *)tg + of_cft(of)->private) = ctx.v; 1175 *(unsigned int *)((void *)tg + of_cft(of)->private) = v;
1172 1176
1173 throtl_log(&tg->service_queue, 1177 throtl_log(&tg->service_queue,
1174 "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", 1178 "limit change rbps=%llu wbps=%llu riops=%u wiops=%u",
@@ -1201,8 +1205,10 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
1201 throtl_schedule_next_dispatch(sq->parent_sq, true); 1205 throtl_schedule_next_dispatch(sq->parent_sq, true);
1202 } 1206 }
1203 1207
1208 ret = 0;
1209out_finish:
1204 blkg_conf_finish(&ctx); 1210 blkg_conf_finish(&ctx);
1205 return nbytes; 1211 return ret ?: nbytes;
1206} 1212}
1207 1213
1208static ssize_t tg_set_conf_u64(struct kernfs_open_file *of, 1214static ssize_t tg_set_conf_u64(struct kernfs_open_file *of,
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index baa8459f7064..ea88d8905bbd 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1747,26 +1747,31 @@ static ssize_t __cfqg_set_weight_device(struct kernfs_open_file *of,
1747 struct cfq_group *cfqg; 1747 struct cfq_group *cfqg;
1748 struct cfq_group_data *cfqgd; 1748 struct cfq_group_data *cfqgd;
1749 int ret; 1749 int ret;
1750 u64 v;
1750 1751
1751 ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx); 1752 ret = blkg_conf_prep(blkcg, &blkcg_policy_cfq, buf, &ctx);
1752 if (ret) 1753 if (ret)
1753 return ret; 1754 return ret;
1754 1755
1756 ret = -EINVAL;
1757 if (sscanf(ctx.body, "%llu", &v) != 1)
1758 goto out_finish;
1759
1755 cfqg = blkg_to_cfqg(ctx.blkg); 1760 cfqg = blkg_to_cfqg(ctx.blkg);
1756 cfqgd = blkcg_to_cfqgd(blkcg); 1761 cfqgd = blkcg_to_cfqgd(blkcg);
1757 1762
1758 ret = -ERANGE; 1763 ret = -ERANGE;
1759 if (!ctx.v || (ctx.v >= CFQ_WEIGHT_MIN && ctx.v <= CFQ_WEIGHT_MAX)) { 1764 if (!v || (v >= CFQ_WEIGHT_MIN && v <= CFQ_WEIGHT_MAX)) {
1760 if (!is_leaf_weight) { 1765 if (!is_leaf_weight) {
1761 cfqg->dev_weight = ctx.v; 1766 cfqg->dev_weight = v;
1762 cfqg->new_weight = ctx.v ?: cfqgd->weight; 1767 cfqg->new_weight = v ?: cfqgd->weight;
1763 } else { 1768 } else {
1764 cfqg->dev_leaf_weight = ctx.v; 1769 cfqg->dev_leaf_weight = v;
1765 cfqg->new_leaf_weight = ctx.v ?: cfqgd->leaf_weight; 1770 cfqg->new_leaf_weight = v ?: cfqgd->leaf_weight;
1766 } 1771 }
1767 ret = 0; 1772 ret = 0;
1768 } 1773 }
1769 1774out_finish:
1770 blkg_conf_finish(&ctx); 1775 blkg_conf_finish(&ctx);
1771 return ret ?: nbytes; 1776 return ret ?: nbytes;
1772} 1777}