blk-wbt: allow wbt to be enabled always through sysfs
authorJens Axboe <axboe@fb.com>
Mon, 28 Nov 2016 16:40:34 +0000 (09:40 -0700)
committerJens Axboe <axboe@fb.com>
Mon, 28 Nov 2016 17:27:03 +0000 (10:27 -0700)
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>
block/blk-sysfs.c
block/blk-wbt.c
block/blk-wbt.h

index f0ca569e276b958518cbf6765547b9c99b861786..a9784149176902beab4b25223989c2d702819f40 100644 (file)
@@ -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;
index 7c0e618d6e7d974ab70d2bc30632c870bf80f1c4..b8647343141f8996704c85d1c0dc88df3c2dff10 100644 (file)
@@ -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);
 
        /*
index 8f485f8e1baf7aeddbe866f5a480a229ea38619c..65f1de519f67ebd72780a07cd12a87a17eafe501 100644 (file)
@@ -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.