summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 f0ca569e276b..a97841491769 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 7c0e618d6e7d..b8647343141f 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 8f485f8e1baf..65f1de519f67 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.