summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2016-11-28 09:40:34 -0700
committerJens Axboe <axboe@fb.com>2016-11-28 10:27:03 -0700
commitd62118b6dd99b8f64350206a6ea6996083b28c9a (patch)
tree18b3dfdeffa55da6509de99f565b789c29599b20
parentfa224eed2b5e0f2f9a57281e9dc733c843d590ad (diff)
downloadlinux-0-day-d62118b6dd99b8f64350206a6ea6996083b28c9a.tar.gz
blk-wbt: allow wbt to be enabled always through sysfs
Currently there's no way to enable wbt if it's not enabled in the kernel config by default for a device. Allow a write to the 'wbt_lat_usec' queue sysfs file to enable wbt. This is useful for both the kernel config case, but also if the device is CFQ managed and it was turned off by default. Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--block/blk-sysfs.c22
-rw-r--r--block/blk-wbt.c3
-rw-r--r--block/blk-wbt.h11
3 files changed, 29 insertions, 7 deletions
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index f0ca569..a978414 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -425,20 +425,30 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
ssize_t ret;
s64 val;
- rwb = q->rq_wb;
- if (!rwb)
- return -EINVAL;
-
ret = queue_var_store64(&val, page);
if (ret < 0)
return ret;
+ if (val < -1)
+ return -EINVAL;
+
+ rwb = q->rq_wb;
+ if (!rwb) {
+ ret = wbt_init(q);
+ if (ret)
+ return ret;
+
+ rwb = q->rq_wb;
+ if (!rwb)
+ return -EINVAL;
+ }
if (val == -1)
rwb->min_lat_nsec = wbt_default_latency_nsec(q);
else if (val >= 0)
rwb->min_lat_nsec = val * 1000ULL;
- else
- return -EINVAL;
+
+ if (rwb->enable_state == WBT_STATE_ON_DEFAULT)
+ rwb->enable_state = WBT_STATE_ON_MANUAL;
wbt_update_limits(rwb);
return count;
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index 7c0e618..b864734 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -673,7 +673,7 @@ void wbt_disable_default(struct request_queue *q)
{
struct rq_wb *rwb = q->rq_wb;
- if (rwb) {
+ if (rwb && rwb->enable_state == WBT_STATE_ON_DEFAULT) {
del_timer_sync(&rwb->window_timer);
rwb->win_nsec = rwb->min_lat_nsec = 0;
wbt_update_limits(rwb);
@@ -721,6 +721,7 @@ int wbt_init(struct request_queue *q)
rwb->last_comp = rwb->last_issue = jiffies;
rwb->queue = q;
rwb->win_nsec = RWB_WINDOW_NSEC;
+ rwb->enable_state = WBT_STATE_ON_DEFAULT;
wbt_update_limits(rwb);
/*
diff --git a/block/blk-wbt.h b/block/blk-wbt.h
index 8f485f8..65f1de5 100644
--- a/block/blk-wbt.h
+++ b/block/blk-wbt.h
@@ -21,6 +21,15 @@ enum {
WBT_NUM_RWQ = 2,
};
+/*
+ * Enable states. Either off, or on by default (done at init time),
+ * or on through manual setup in sysfs.
+ */
+enum {
+ WBT_STATE_ON_DEFAULT = 1,
+ WBT_STATE_ON_MANUAL = 2,
+};
+
static inline void wbt_clear_state(struct blk_issue_stat *stat)
{
stat->time &= BLK_STAT_TIME_MASK;
@@ -61,6 +70,8 @@ struct rq_wb {
int scale_step;
bool scaled_max;
+ short enable_state; /* WBT_STATE_* */
+
/*
* Number of consecutive periods where we don't have enough
* information to make a firm scale up/down decision.