blk-wbt: factor out a helper wbt_set_lat()

To move implementation details inside blk-wbt.c, prepare to fix possible
deadlock to call wbt_init() while queue is frozen in the next patch.

Reviewed-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Signed-off-by: Yu Kuai <yukuai@fnnas.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Yu Kuai 2026-02-02 16:05:16 +08:00 committed by Jens Axboe
parent 06564bae93
commit 2751b90051
3 changed files with 51 additions and 45 deletions

View file

@ -636,11 +636,8 @@ out:
static ssize_t queue_wb_lat_store(struct gendisk *disk, const char *page,
size_t count)
{
struct request_queue *q = disk->queue;
struct rq_qos *rqos;
ssize_t ret;
s64 val;
unsigned int memflags;
ret = queue_var_store64(&val, page);
if (ret < 0)
@ -648,40 +645,8 @@ static ssize_t queue_wb_lat_store(struct gendisk *disk, const char *page,
if (val < -1)
return -EINVAL;
/*
* 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;
}
ret = count;
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;
ret = wbt_set_lat(disk, val);
return ret ? ret : count;
}
QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec");

View file

@ -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;
}

View file

@ -4,16 +4,13 @@
#ifdef CONFIG_BLK_WBT
int wbt_init(struct gendisk *disk);
void wbt_init_enable_default(struct gendisk *disk);
void wbt_disable_default(struct gendisk *disk);
void wbt_enable_default(struct gendisk *disk);
u64 wbt_get_min_lat(struct request_queue *q);
void wbt_set_min_lat(struct request_queue *q, u64 val);
bool wbt_disabled(struct request_queue *);
u64 wbt_default_latency_nsec(struct request_queue *);
bool wbt_disabled(struct request_queue *q);
int wbt_set_lat(struct gendisk *disk, s64 val);
#else