Add 'wbt_lat_us' to block device' queue sysfs only when we open 'wbt' blk-rq-qos policy. And do some code cleanup as we needn't to export those wbt interfaces. Signed-off-by: Wang Jianchao (Kuaishou) <jianchao.wan9@xxxxxxxxx> --- block/blk-sysfs.c | 71 ---------------- block/blk-wbt.c | 201 +++++++++++++++++++++++++++------------------- block/blk-wbt.h | 28 ------- block/blk.h | 6 ++ 4 files changed, 125 insertions(+), 181 deletions(-) diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 052b5f03fc73..1b321edd7ba7 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -20,12 +20,6 @@ #include "blk-wbt.h" #include "blk-throttle.h" -struct queue_sysfs_entry { - struct attribute attr; - ssize_t (*show)(struct request_queue *, char *); - ssize_t (*store)(struct request_queue *, const char *, size_t); -}; - static ssize_t queue_var_show(unsigned long var, char *page) { @@ -47,19 +41,6 @@ queue_var_store(unsigned long *var, const char *page, size_t count) return count; } -static ssize_t queue_var_store64(s64 *var, const char *page) -{ - int err; - s64 v; - - err = kstrtos64(page, 10, &v); - if (err < 0) - return err; - - *var = v; - return 0; -} - static ssize_t queue_requests_show(struct request_queue *q, char *page) { return queue_var_show(q->nr_requests, page); @@ -461,56 +442,6 @@ static ssize_t queue_io_timeout_store(struct request_queue *q, const char *page, return count; } -static ssize_t queue_wb_lat_show(struct request_queue *q, char *page) -{ - if (!wbt_opened(q)) - return -EINVAL; - - return sprintf(page, "%llu\n", div_u64(wbt_get_min_lat(q), 1000)); -} - -static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page, - size_t count) -{ - ssize_t ret; - s64 val; - - ret = queue_var_store64(&val, page); - if (ret < 0) - return ret; - if (val < -1) - return -EINVAL; - - if (!wbt_opened(q)) { - ret = wbt_init(q); - if (ret) - return ret; - } - - if (val == -1) - val = wbt_default_latency_nsec(q); - else if (val >= 0) - val *= 1000ULL; - - if (wbt_get_min_lat(q) == val) - return count; - - /* - * 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. - */ - blk_mq_freeze_queue(q); - blk_mq_quiesce_queue(q); - - wbt_set_min_lat(q, val); - - blk_mq_unquiesce_queue(q); - blk_mq_unfreeze_queue(q); - - return count; -} - static ssize_t queue_wc_show(struct request_queue *q, char *page) { if (test_bit(QUEUE_FLAG_WC, &q->queue_flags)) @@ -604,7 +535,6 @@ QUEUE_RW_ENTRY(queue_wc, "write_cache"); QUEUE_RO_ENTRY(queue_fua, "fua"); QUEUE_RO_ENTRY(queue_dax, "dax"); QUEUE_RW_ENTRY(queue_io_timeout, "io_timeout"); -QUEUE_RW_ENTRY(queue_wb_lat, "wbt_lat_usec"); QUEUE_RO_ENTRY(queue_virt_boundary_mask, "virt_boundary_mask"); #ifdef CONFIG_BLK_DEV_THROTTLING_LOW @@ -661,7 +591,6 @@ static struct attribute *queue_attrs[] = { &queue_wc_entry.attr, &queue_fua_entry.attr, &queue_dax_entry.attr, - &queue_wb_lat_entry.attr, &queue_poll_delay_entry.attr, &queue_io_timeout_entry.attr, #ifdef CONFIG_BLK_DEV_THROTTLING_LOW diff --git a/block/blk-wbt.c b/block/blk-wbt.c index 44a920d83475..bbec3b394273 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -24,7 +24,9 @@ #include <linux/slab.h> #include <linux/backing-dev.h> #include <linux/swap.h> +#include <linux/sysfs.h> +#include "blk.h" #include "blk-wbt.h" #include "blk-rq-qos.h" @@ -38,15 +40,6 @@ static inline struct rq_qos *wbt_rq_qos(struct request_queue *q) return rq_qos_get(q, wbt_rqos_ops.id); } -bool wbt_opened(struct request_queue *q) -{ - struct rq_qos *rqos = wbt_rq_qos(q); - - rq_qos_put(rqos); - - return !!rqos; -} - static inline void wbt_clear_state(struct request *rq) { rq->wbt_flags = 0; @@ -438,33 +431,6 @@ static void wbt_update_limits(struct rq_wb *rwb) rwb_wake_all(rwb); } -u64 wbt_get_min_lat(struct request_queue *q) -{ - struct rq_qos *rqos = wbt_rq_qos(q); - u64 nsec; - - if (!rqos) - return 0; - - nsec = RQWB(rqos)->min_lat_nsec; - rq_qos_put(rqos); - - return nsec; -} - -void wbt_set_min_lat(struct request_queue *q, u64 val) -{ - struct rq_qos *rqos = wbt_rq_qos(q); - - if (!rqos) - return; - RQWB(rqos)->min_lat_nsec = val; - RQWB(rqos)->enable_state = WBT_STATE_ON_MANUAL; - wbt_update_limits(RQWB(rqos)); - rq_qos_put(rqos); -} - - static bool close_io(struct rq_wb *rwb) { const unsigned long now = jiffies; @@ -660,32 +626,7 @@ void wbt_set_write_cache(struct request_queue *q, bool write_cache_on) } } -/* - * Enable wbt if defaults are configured that way - */ -void wbt_enable_default(struct request_queue *q) -{ - struct rq_qos *rqos = wbt_rq_qos(q); - - /* Throttling already enabled? */ - if (rqos) { - if (RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT) - RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT; - - rq_qos_put(rqos); - return; - } - - /* Queue not registered? Maybe shutting down... */ - if (!blk_queue_registered(q)) - return; - - if (queue_is_mq(q) && IS_ENABLED(CONFIG_BLK_WBT_MQ)) - wbt_init(q); -} -EXPORT_SYMBOL_GPL(wbt_enable_default); - -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 @@ -716,7 +657,67 @@ static void wbt_queue_depth_changed(struct rq_qos *rqos) wbt_update_limits(RQWB(rqos)); } -static void wbt_exit(struct rq_qos *rqos) +static ssize_t wbt_lat_show(struct request_queue *q, char *page) +{ + struct rq_qos *rqos = wbt_rq_qos(q); + ssize_t ret; + + ret = sprintf(page, "%llu\n", div_u64(RQWB(rqos)->min_lat_nsec, 1000)); + + rq_qos_put(rqos); + + return ret; +} + +static ssize_t wbt_lat_store(struct request_queue *q, const char *page, + size_t count) +{ + struct rq_qos *rqos; + struct rq_wb *rwb; + ssize_t ret; + s64 val; + + ret = kstrtos64(page, 10, &val); + if (ret < 0) + return ret; + + if (val < -1) + return -EINVAL; + + if (val == -1) + val = wbt_default_latency_nsec(q); + else if (val >= 0) + val *= 1000ULL; + + rqos = wbt_rq_qos(q); + rwb = RQWB(rqos); + + if (rwb->min_lat_nsec == val) + goto out; + /* + * 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. + */ + blk_mq_freeze_queue(q); + blk_mq_quiesce_queue(q); + + rwb->min_lat_nsec = val; + rwb->enable_state = WBT_STATE_ON_MANUAL; + wbt_update_limits(rwb); + + blk_mq_unquiesce_queue(q); + blk_mq_unfreeze_queue(q); + +out: + rq_qos_put(rqos); + return count; +} + +static struct queue_sysfs_entry wbt_attr = + __ATTR(wbt_lat_usec, 0644, wbt_lat_show, wbt_lat_store); + +static void __wbt_exit(struct rq_qos *rqos) { struct rq_wb *rwb = RQWB(rqos); struct request_queue *q = rqos->q; @@ -727,6 +728,12 @@ static void wbt_exit(struct rq_qos *rqos) kfree(rwb); } +static void wbt_exit(struct rq_qos *rqos) +{ + sysfs_remove_file(&rqos->q->kobj, &wbt_attr.attr); + __wbt_exit(rqos); +} + /* * Disable wbt, if enabled by default. */ @@ -835,26 +842,10 @@ static const struct blk_mq_debugfs_attr wbt_debugfs_attrs[] = { }; #endif -static struct rq_qos_ops wbt_rqos_ops = { - .name = "wbt", - .throttle = wbt_wait, - .issue = wbt_issue, - .track = wbt_track, - .requeue = wbt_requeue, - .done = wbt_done, - .cleanup = wbt_cleanup, - .queue_depth_changed = wbt_queue_depth_changed, - .exit = wbt_exit, - .init = wbt_init, -#ifdef CONFIG_BLK_DEBUG_FS - .debugfs_attrs = wbt_debugfs_attrs, -#endif -}; - -int wbt_init(struct request_queue *q) +static int wbt_init(struct request_queue *q) { struct rq_wb *rwb; - int i; + int i, ret; rwb = kzalloc(sizeof(*rwb), GFP_KERNEL); if (!rwb) @@ -886,9 +877,54 @@ int wbt_init(struct request_queue *q) wbt_queue_depth_changed(&rwb->rqos); wbt_set_write_cache(q, test_bit(QUEUE_FLAG_WC, &q->queue_flags)); - return 0; + ret = sysfs_create_file(&q->kobj, &wbt_attr.attr); + if (ret < 0) + __wbt_exit(&rwb->rqos); + + return ret; } +static struct rq_qos_ops wbt_rqos_ops = { + .name = "wbt", + .throttle = wbt_wait, + .issue = wbt_issue, + .track = wbt_track, + .requeue = wbt_requeue, + .done = wbt_done, + .cleanup = wbt_cleanup, + .queue_depth_changed = wbt_queue_depth_changed, + .exit = wbt_exit, + .init = wbt_init, +#ifdef CONFIG_BLK_DEBUG_FS + .debugfs_attrs = wbt_debugfs_attrs, +#endif +}; + +/* + * Enable wbt if defaults are configured that way + */ +void wbt_enable_default(struct request_queue *q) +{ + struct rq_qos *rqos = wbt_rq_qos(q); + + /* Throttling already enabled? */ + if (rqos) { + if (RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT) + RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT; + + rq_qos_put(rqos); + return; + } + + /* Queue not registered? Maybe shutting down... */ + if (!blk_queue_registered(q)) + return; + + if (queue_is_mq(q) && IS_ENABLED(CONFIG_BLK_WBT_MQ)) + wbt_init(q); +} +EXPORT_SYMBOL_GPL(wbt_enable_default); + static __init int wbt_mod_init(void) { return rq_qos_register(&wbt_rqos_ops); @@ -898,5 +934,6 @@ static __exit void wbt_mod_exit(void) { return rq_qos_unregister(&wbt_rqos_ops); } + module_init(wbt_mod_init); module_exit(wbt_mod_exit); diff --git a/block/blk-wbt.h b/block/blk-wbt.h index f128dcf662db..b9ed3f373b5a 100644 --- a/block/blk-wbt.h +++ b/block/blk-wbt.h @@ -88,32 +88,16 @@ static inline unsigned int wbt_inflight(struct rq_wb *rwb) #ifdef CONFIG_BLK_WBT -bool wbt_opened(struct request_queue *q); -int wbt_init(struct request_queue *); void wbt_disable_default(struct request_queue *); void wbt_enable_default(struct request_queue *); -u64 wbt_get_min_lat(struct request_queue *q); -void wbt_set_min_lat(struct request_queue *q, u64 val); - void wbt_set_write_cache(struct request_queue *, bool); -u64 wbt_default_latency_nsec(struct request_queue *); - #else -bool wbt_opened(struct request_queue *q) -{ - return false; -} - static inline void wbt_track(struct request *rq, enum wbt_flags flags) { } -static inline int wbt_init(struct request_queue *q) -{ - return -EINVAL; -} static inline void wbt_disable_default(struct request_queue *q) { } @@ -123,18 +107,6 @@ static inline void wbt_enable_default(struct request_queue *q) static inline void wbt_set_write_cache(struct request_queue *q, bool wc) { } -static inline u64 wbt_get_min_lat(struct request_queue *q) -{ - return 0; -} -static inline void wbt_set_min_lat(struct request_queue *q, u64 val) -{ -} -static inline u64 wbt_default_latency_nsec(struct request_queue *q) -{ - return 0; -} - #endif /* CONFIG_BLK_WBT */ #endif diff --git a/block/blk.h b/block/blk.h index 1a314257b6a3..2ec7510c080c 100644 --- a/block/blk.h +++ b/block/blk.h @@ -14,6 +14,12 @@ struct elevator_type; extern struct dentry *blk_debugfs_root; +struct queue_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct request_queue *, char *); + ssize_t (*store)(struct request_queue *, const char *, size_t); +}; + struct blk_flush_queue { unsigned int flush_pending_idx:1; unsigned int flush_running_idx:1; -- 2.17.1