aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-throttle.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-04-01 14:38:43 -0700
committerTejun Heo <tj@kernel.org>2012-04-01 14:38:43 -0700
commit60c2bc2d5a12369deef395cda41638d7e6b6bf19 (patch)
tree67fb6ace87a930215f800f0a96bb33f9773231c7 /block/blk-throttle.c
parent44ea53de46a8b01a65ae6217f47e00b516725190 (diff)
downloadkernel_goldelico_gta04-60c2bc2d5a12369deef395cda41638d7e6b6bf19.zip
kernel_goldelico_gta04-60c2bc2d5a12369deef395cda41638d7e6b6bf19.tar.gz
kernel_goldelico_gta04-60c2bc2d5a12369deef395cda41638d7e6b6bf19.tar.bz2
blkcg: move conf/stat file handling code to policies
blkcg conf/stat handling is convoluted in that details which belong to specific policy implementations are all out in blkcg core and then policies hook into core layer to access and manipulate confs and stats. This sadly achieves both inflexibility (confs/stats can't be modified without messing with blkcg core) and complexity (all the call-ins and call-backs). The previous patches restructured conf and stat handling code such that they can be separated out. This patch relocates the file handling part. All conf/stat file handling code which belongs to BLKIO_POLICY_PROP is moved to cfq-iosched.c and all BKLIO_POLICY_THROTL code to blk-throtl.c. The move is verbatim except for blkio_update_group_{weight|bps|iops}() callbacks which relays conf changes to policies. The configuration settings are handled in policies themselves so the relaying isn't necessary. Conf setting functions are modified to directly call per-policy update functions and the relaying mechanism is dropped. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r--block/blk-throttle.c163
1 files changed, 134 insertions, 29 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 1cc6c23d..fb6f257 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -804,6 +804,11 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay)
}
}
+/*
+ * Can not take queue lock in update functions as queue lock under
+ * blkcg_lock is not allowed. Under other paths we take blkcg_lock under
+ * queue_lock.
+ */
static void throtl_update_blkio_group_common(struct throtl_data *td,
struct throtl_grp *tg)
{
@@ -813,51 +818,158 @@ static void throtl_update_blkio_group_common(struct throtl_data *td,
throtl_schedule_delayed_work(td, 0);
}
-/*
- * For all update functions, @q should be a valid pointer because these
- * update functions are called under blkcg_lock, that means, blkg is
- * valid and in turn @q is valid. queue exit path can not race because
- * of blkcg_lock
- *
- * Can not take queue lock in update functions as queue lock under blkcg_lock
- * is not allowed. Under other paths we take blkcg_lock under queue_lock.
- */
-static void throtl_update_blkio_group_read_bps(struct request_queue *q,
- struct blkio_group *blkg, u64 read_bps)
+static u64 blkg_prfill_conf_u64(struct seq_file *sf,
+ struct blkg_policy_data *pd, int off)
+{
+ u64 v = *(u64 *)((void *)&pd->conf + off);
+
+ if (!v)
+ return 0;
+ return __blkg_prfill_u64(sf, pd, v);
+}
+
+static int blkcg_print_conf_u64(struct cgroup *cgrp, struct cftype *cft,
+ struct seq_file *sf)
+{
+ blkcg_print_blkgs(sf, cgroup_to_blkio_cgroup(cgrp),
+ blkg_prfill_conf_u64, BLKIO_POLICY_THROTL,
+ cft->private, false);
+ return 0;
+}
+
+static void throtl_update_blkio_group_read_bps(struct blkio_group *blkg,
+ u64 read_bps)
{
struct throtl_grp *tg = blkg_to_tg(blkg);
tg->bps[READ] = read_bps;
- throtl_update_blkio_group_common(q->td, tg);
+ throtl_update_blkio_group_common(blkg->q->td, tg);
}
-static void throtl_update_blkio_group_write_bps(struct request_queue *q,
- struct blkio_group *blkg, u64 write_bps)
+static void throtl_update_blkio_group_write_bps(struct blkio_group *blkg,
+ u64 write_bps)
{
struct throtl_grp *tg = blkg_to_tg(blkg);
tg->bps[WRITE] = write_bps;
- throtl_update_blkio_group_common(q->td, tg);
+ throtl_update_blkio_group_common(blkg->q->td, tg);
}
-static void throtl_update_blkio_group_read_iops(struct request_queue *q,
- struct blkio_group *blkg, unsigned int read_iops)
+static void throtl_update_blkio_group_read_iops(struct blkio_group *blkg,
+ u64 read_iops)
{
struct throtl_grp *tg = blkg_to_tg(blkg);
tg->iops[READ] = read_iops;
- throtl_update_blkio_group_common(q->td, tg);
+ throtl_update_blkio_group_common(blkg->q->td, tg);
}
-static void throtl_update_blkio_group_write_iops(struct request_queue *q,
- struct blkio_group *blkg, unsigned int write_iops)
+static void throtl_update_blkio_group_write_iops(struct blkio_group *blkg,
+ u64 write_iops)
{
struct throtl_grp *tg = blkg_to_tg(blkg);
tg->iops[WRITE] = write_iops;
- throtl_update_blkio_group_common(q->td, tg);
+ throtl_update_blkio_group_common(blkg->q->td, tg);
+}
+
+static int blkcg_set_conf_u64(struct cgroup *cgrp, struct cftype *cft,
+ const char *buf,
+ void (*update)(struct blkio_group *, u64))
+{
+ struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgrp);
+ struct blkg_policy_data *pd;
+ struct blkg_conf_ctx ctx;
+ int ret;
+
+ ret = blkg_conf_prep(blkcg, buf, &ctx);
+ if (ret)
+ return ret;
+
+ ret = -EINVAL;
+ pd = ctx.blkg->pd[BLKIO_POLICY_THROTL];
+ if (pd) {
+ *(u64 *)((void *)&pd->conf + cft->private) = ctx.v;
+ update(ctx.blkg, ctx.v ?: -1);
+ ret = 0;
+ }
+
+ blkg_conf_finish(&ctx);
+ return ret;
}
+static int blkcg_set_conf_bps_r(struct cgroup *cgrp, struct cftype *cft,
+ const char *buf)
+{
+ return blkcg_set_conf_u64(cgrp, cft, buf,
+ throtl_update_blkio_group_read_bps);
+}
+
+static int blkcg_set_conf_bps_w(struct cgroup *cgrp, struct cftype *cft,
+ const char *buf)
+{
+ return blkcg_set_conf_u64(cgrp, cft, buf,
+ throtl_update_blkio_group_write_bps);
+}
+
+static int blkcg_set_conf_iops_r(struct cgroup *cgrp, struct cftype *cft,
+ const char *buf)
+{
+ return blkcg_set_conf_u64(cgrp, cft, buf,
+ throtl_update_blkio_group_read_iops);
+}
+
+static int blkcg_set_conf_iops_w(struct cgroup *cgrp, struct cftype *cft,
+ const char *buf)
+{
+ return blkcg_set_conf_u64(cgrp, cft, buf,
+ throtl_update_blkio_group_write_iops);
+}
+
+static struct cftype throtl_files[] = {
+ {
+ .name = "throttle.read_bps_device",
+ .private = offsetof(struct blkio_group_conf, bps[READ]),
+ .read_seq_string = blkcg_print_conf_u64,
+ .write_string = blkcg_set_conf_bps_r,
+ .max_write_len = 256,
+ },
+ {
+ .name = "throttle.write_bps_device",
+ .private = offsetof(struct blkio_group_conf, bps[WRITE]),
+ .read_seq_string = blkcg_print_conf_u64,
+ .write_string = blkcg_set_conf_bps_w,
+ .max_write_len = 256,
+ },
+ {
+ .name = "throttle.read_iops_device",
+ .private = offsetof(struct blkio_group_conf, iops[READ]),
+ .read_seq_string = blkcg_print_conf_u64,
+ .write_string = blkcg_set_conf_iops_r,
+ .max_write_len = 256,
+ },
+ {
+ .name = "throttle.write_iops_device",
+ .private = offsetof(struct blkio_group_conf, iops[WRITE]),
+ .read_seq_string = blkcg_print_conf_u64,
+ .write_string = blkcg_set_conf_iops_w,
+ .max_write_len = 256,
+ },
+ {
+ .name = "throttle.io_service_bytes",
+ .private = BLKCG_STAT_PRIV(BLKIO_POLICY_THROTL,
+ offsetof(struct blkio_group_stats_cpu, service_bytes)),
+ .read_seq_string = blkcg_print_cpu_rwstat,
+ },
+ {
+ .name = "throttle.io_serviced",
+ .private = BLKCG_STAT_PRIV(BLKIO_POLICY_THROTL,
+ offsetof(struct blkio_group_stats_cpu, serviced)),
+ .read_seq_string = blkcg_print_cpu_rwstat,
+ },
+ { } /* terminate */
+};
+
static void throtl_shutdown_wq(struct request_queue *q)
{
struct throtl_data *td = q->td;
@@ -868,17 +980,10 @@ static void throtl_shutdown_wq(struct request_queue *q)
static struct blkio_policy_type blkio_policy_throtl = {
.ops = {
.blkio_init_group_fn = throtl_init_blkio_group,
- .blkio_update_group_read_bps_fn =
- throtl_update_blkio_group_read_bps,
- .blkio_update_group_write_bps_fn =
- throtl_update_blkio_group_write_bps,
- .blkio_update_group_read_iops_fn =
- throtl_update_blkio_group_read_iops,
- .blkio_update_group_write_iops_fn =
- throtl_update_blkio_group_write_iops,
},
.plid = BLKIO_POLICY_THROTL,
.pdata_size = sizeof(struct throtl_grp),
+ .cftypes = throtl_files,
};
bool blk_throtl_bio(struct request_queue *q, struct bio *bio)