summaryrefslogtreecommitdiff
path: root/block/blk-wbt.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-wbt.c')
-rw-r--r--block/blk-wbt.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index 8e025834f2fb..0a37d97bda75 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -93,6 +93,8 @@ struct rq_wb {
struct rq_depth rq_depth;
};
+static int wbt_init(struct gendisk *disk);
+
static inline struct rq_wb *RQWB(struct rq_qos *rqos)
{
return container_of(rqos, struct rq_wb, rqos);
@@ -506,7 +508,7 @@ u64 wbt_get_min_lat(struct request_queue *q)
return RQWB(rqos)->min_lat_nsec;
}
-void wbt_set_min_lat(struct request_queue *q, u64 val)
+static void wbt_set_min_lat(struct request_queue *q, u64 val)
{
struct rq_qos *rqos = wbt_rq_qos(q);
if (!rqos)
@@ -741,7 +743,7 @@ void wbt_init_enable_default(struct gendisk *disk)
WARN_ON_ONCE(wbt_init(disk));
}
-u64 wbt_default_latency_nsec(struct request_queue *q)
+static u64 wbt_default_latency_nsec(struct request_queue *q)
{
/*
* We default to 2msec for non-rotational storage, and 75msec
@@ -901,7 +903,7 @@ static const struct rq_qos_ops wbt_rqos_ops = {
#endif
};
-int wbt_init(struct gendisk *disk)
+static int wbt_init(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
struct rq_wb *rwb;
@@ -948,3 +950,45 @@ err_free:
return ret;
}
+
+int wbt_set_lat(struct gendisk *disk, s64 val)
+{
+ struct request_queue *q = disk->queue;
+ unsigned int memflags;
+ struct rq_qos *rqos;
+ int ret = 0;
+
+ /*
+ * Ensure that the queue is idled, in case the latency update
+ * ends up either enabling or disabling wbt completely. We can't
+ * have IO inflight if that happens.
+ */
+ memflags = blk_mq_freeze_queue(q);
+
+ rqos = wbt_rq_qos(q);
+ if (!rqos) {
+ ret = wbt_init(disk);
+ if (ret)
+ goto out;
+ }
+
+ if (val == -1)
+ val = wbt_default_latency_nsec(q);
+ else if (val >= 0)
+ val *= 1000ULL;
+
+ if (wbt_get_min_lat(q) == val)
+ goto out;
+
+ blk_mq_quiesce_queue(q);
+
+ mutex_lock(&disk->rqos_state_mutex);
+ wbt_set_min_lat(q, val);
+ mutex_unlock(&disk->rqos_state_mutex);
+
+ blk_mq_unquiesce_queue(q);
+out:
+ blk_mq_unfreeze_queue(q, memflags);
+
+ return ret;
+}