Commit 31487965 authored by Yu Kuai's avatar Yu Kuai
Browse files

blk-io-hierarchy: support new rq based stage plug

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: default avatarYu Kuai <yukuai3@huawei.com>
parent 393b259e
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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
+12 −0
Original line number Diff line number Diff line
@@ -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)
{
+11 −1
Original line number Diff line number Diff line
@@ -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. */
+7 −1
Original line number Diff line number Diff line
@@ -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);