hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/release-management/issues/IB4E8P CVE: NA
--------------------------------
Like blk-throttle, following new debugfs entries will be created for rq-based disk:
/sys/kernel/debug/block/sda/blk_io_hierarchy/ |-- plug | |-- io_dump | |-- stats | `-- threshold
User can use them to analyze how IO behaves in plug.
Signed-off-by: Yu Kuai yukuai3@huawei.com --- block/blk-io-hierarchy/Kconfig | 10 ++++++++++ block/blk-io-hierarchy/stats.h | 12 ++++++++++++ block/blk-mq.c | 12 +++++++++++- block/blk-sysfs.c | 8 +++++++- 4 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/block/blk-io-hierarchy/Kconfig b/block/blk-io-hierarchy/Kconfig index 54c2cb88199a..342c6a72fffb 100644 --- a/block/blk-io-hierarchy/Kconfig +++ b/block/blk-io-hierarchy/Kconfig @@ -69,4 +69,14 @@ config HIERARCHY_GETTAG
If unsure, say N.
+config HIERARCHY_PLUG + bool "Enable hierarchy stats layer plug" + default n + help + Enabling this lets blk hierarchy stats to record additional information + for plug. Such information can be helpful to debug performance + and problems like io hang. + + If unsure, say N. + endif diff --git a/block/blk-io-hierarchy/stats.h b/block/blk-io-hierarchy/stats.h index 8166e71969bd..dc397a90c4b1 100644 --- a/block/blk-io-hierarchy/stats.h +++ b/block/blk-io-hierarchy/stats.h @@ -186,6 +186,14 @@ static inline void rq_list_hierarchy_end_io_acct(struct list_head *head, __rq_hierarchy_end_io_acct(rq, hstage); }
+static inline void plug_list_hierarchy_end_io_acct(struct blk_plug *plug) +{ + struct request *rq; + + rq_list_for_each(&plug->mq_list, rq) + rq_hierarchy_end_io_acct(rq, STAGE_PLUG); +} + static inline void blk_rq_hierarchy_stats_init(struct request *rq) { rq->stage = NR_RQ_STAGE_GROUPS; @@ -339,6 +347,10 @@ rq_list_hierarchy_end_io_acct(struct list_head *head, enum stage_group stage) { }
+static inline void plug_list_hierarchy_end_io_acct(struct blk_plug *plug) +{ +} + static inline void blk_rq_hierarchy_stats_init(struct request *rq) { diff --git a/block/blk-mq.c b/block/blk-mq.c index f32644ca3c12..bf1329ada77b 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1308,6 +1308,8 @@ static void blk_add_rq_to_plug(struct blk_plug *plug, struct request *rq) { struct request *last = rq_list_peek(&plug->mq_list);
+ rq_hierarchy_start_io_acct(rq, STAGE_PLUG); + if (!plug->rq_count) { trace_block_plug(rq->q); } else if (plug->rq_count >= blk_plug_max_rq_count(plug) || @@ -2840,6 +2842,8 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) */ if (plug->rq_count == 0) return; + + plug_list_hierarchy_end_io_acct(plug); plug->rq_count = 0;
if (!plug->multiple_queues && !plug->has_elevator && !from_schedule) { @@ -4380,12 +4384,18 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, } EXPORT_SYMBOL(blk_mq_init_allocated_queue);
+static void blk_mq_unregister_default_hierarchy(struct request_queue *q) +{ + blk_mq_unregister_hierarchy(q, STAGE_GETTAG); + blk_mq_unregister_hierarchy(q, STAGE_PLUG); +} + /* tags can _not_ be used after returning from blk_mq_exit_queue */ void blk_mq_exit_queue(struct request_queue *q) { struct blk_mq_tag_set *set = q->tag_set;
- blk_mq_unregister_hierarchy(q, STAGE_GETTAG); + blk_mq_unregister_default_hierarchy(q); /* Checks hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED. */ blk_mq_exit_hw_queues(q, set, set->nr_hw_queues); /* May clear BLK_MQ_F_TAG_QUEUE_SHARED in hctx->flags. */ diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 65be33558d28..1539a137502e 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -819,6 +819,12 @@ static void blk_debugfs_remove(struct gendisk *disk) mutex_unlock(&q->debugfs_mutex); }
+static void blk_mq_register_default_hierarchy(struct request_queue *q) +{ + blk_mq_register_hierarchy(q, STAGE_GETTAG); + blk_mq_register_hierarchy(q, STAGE_PLUG); +} + /** * blk_register_queue - register a block layer queue with sysfs * @disk: Disk of which the request queue should be registered with sysfs. @@ -862,7 +868,7 @@ int blk_register_queue(struct gendisk *disk) goto out_elv_unregister;
if (queue_is_mq(q)) - blk_mq_register_hierarchy(q, STAGE_GETTAG); + blk_mq_register_default_hierarchy(q);
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q); wbt_enable_default(disk);