162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  MQ Deadline i/o scheduler - adaptation of the legacy deadline scheduler,
462306a36Sopenharmony_ci *  for the blk-mq scheduling framework
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *  Copyright (C) 2016 Jens Axboe <axboe@kernel.dk>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include <linux/fs.h>
1062306a36Sopenharmony_ci#include <linux/blkdev.h>
1162306a36Sopenharmony_ci#include <linux/bio.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/slab.h>
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/compiler.h>
1662306a36Sopenharmony_ci#include <linux/rbtree.h>
1762306a36Sopenharmony_ci#include <linux/sbitmap.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <trace/events/block.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "elevator.h"
2262306a36Sopenharmony_ci#include "blk.h"
2362306a36Sopenharmony_ci#include "blk-mq.h"
2462306a36Sopenharmony_ci#include "blk-mq-debugfs.h"
2562306a36Sopenharmony_ci#include "blk-mq-sched.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/*
2862306a36Sopenharmony_ci * See Documentation/block/deadline-iosched.rst
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_cistatic const int read_expire = HZ / 2;  /* max time before a read is submitted. */
3162306a36Sopenharmony_cistatic const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * Time after which to dispatch lower priority requests even if higher
3462306a36Sopenharmony_ci * priority requests are pending.
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_cistatic const int prio_aging_expire = 10 * HZ;
3762306a36Sopenharmony_cistatic const int writes_starved = 2;    /* max times reads can starve a write */
3862306a36Sopenharmony_cistatic const int fifo_batch = 16;       /* # of sequential requests treated as one
3962306a36Sopenharmony_ci				     by the above parameters. For throughput. */
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cienum dd_data_dir {
4262306a36Sopenharmony_ci	DD_READ		= READ,
4362306a36Sopenharmony_ci	DD_WRITE	= WRITE,
4462306a36Sopenharmony_ci};
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cienum { DD_DIR_COUNT = 2 };
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cienum dd_prio {
4962306a36Sopenharmony_ci	DD_RT_PRIO	= 0,
5062306a36Sopenharmony_ci	DD_BE_PRIO	= 1,
5162306a36Sopenharmony_ci	DD_IDLE_PRIO	= 2,
5262306a36Sopenharmony_ci	DD_PRIO_MAX	= 2,
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cienum { DD_PRIO_COUNT = 3 };
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/*
5862306a36Sopenharmony_ci * I/O statistics per I/O priority. It is fine if these counters overflow.
5962306a36Sopenharmony_ci * What matters is that these counters are at least as wide as
6062306a36Sopenharmony_ci * log2(max_outstanding_requests).
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_cistruct io_stats_per_prio {
6362306a36Sopenharmony_ci	uint32_t inserted;
6462306a36Sopenharmony_ci	uint32_t merged;
6562306a36Sopenharmony_ci	uint32_t dispatched;
6662306a36Sopenharmony_ci	atomic_t completed;
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci/*
7062306a36Sopenharmony_ci * Deadline scheduler data per I/O priority (enum dd_prio). Requests are
7162306a36Sopenharmony_ci * present on both sort_list[] and fifo_list[].
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistruct dd_per_prio {
7462306a36Sopenharmony_ci	struct list_head dispatch;
7562306a36Sopenharmony_ci	struct rb_root sort_list[DD_DIR_COUNT];
7662306a36Sopenharmony_ci	struct list_head fifo_list[DD_DIR_COUNT];
7762306a36Sopenharmony_ci	/* Position of the most recently dispatched request. */
7862306a36Sopenharmony_ci	sector_t latest_pos[DD_DIR_COUNT];
7962306a36Sopenharmony_ci	struct io_stats_per_prio stats;
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistruct deadline_data {
8362306a36Sopenharmony_ci	/*
8462306a36Sopenharmony_ci	 * run time data
8562306a36Sopenharmony_ci	 */
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	struct dd_per_prio per_prio[DD_PRIO_COUNT];
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/* Data direction of latest dispatched request. */
9062306a36Sopenharmony_ci	enum dd_data_dir last_dir;
9162306a36Sopenharmony_ci	unsigned int batching;		/* number of sequential requests made */
9262306a36Sopenharmony_ci	unsigned int starved;		/* times reads have starved writes */
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/*
9562306a36Sopenharmony_ci	 * settings that change how the i/o scheduler behaves
9662306a36Sopenharmony_ci	 */
9762306a36Sopenharmony_ci	int fifo_expire[DD_DIR_COUNT];
9862306a36Sopenharmony_ci	int fifo_batch;
9962306a36Sopenharmony_ci	int writes_starved;
10062306a36Sopenharmony_ci	int front_merges;
10162306a36Sopenharmony_ci	u32 async_depth;
10262306a36Sopenharmony_ci	int prio_aging_expire;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	spinlock_t lock;
10562306a36Sopenharmony_ci	spinlock_t zone_lock;
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci/* Maps an I/O priority class to a deadline scheduler priority. */
10962306a36Sopenharmony_cistatic const enum dd_prio ioprio_class_to_prio[] = {
11062306a36Sopenharmony_ci	[IOPRIO_CLASS_NONE]	= DD_BE_PRIO,
11162306a36Sopenharmony_ci	[IOPRIO_CLASS_RT]	= DD_RT_PRIO,
11262306a36Sopenharmony_ci	[IOPRIO_CLASS_BE]	= DD_BE_PRIO,
11362306a36Sopenharmony_ci	[IOPRIO_CLASS_IDLE]	= DD_IDLE_PRIO,
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic inline struct rb_root *
11762306a36Sopenharmony_cideadline_rb_root(struct dd_per_prio *per_prio, struct request *rq)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	return &per_prio->sort_list[rq_data_dir(rq)];
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci/*
12362306a36Sopenharmony_ci * Returns the I/O priority class (IOPRIO_CLASS_*) that has been assigned to a
12462306a36Sopenharmony_ci * request.
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_cistatic u8 dd_rq_ioclass(struct request *rq)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	return IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/*
13262306a36Sopenharmony_ci * get the request before `rq' in sector-sorted order
13362306a36Sopenharmony_ci */
13462306a36Sopenharmony_cistatic inline struct request *
13562306a36Sopenharmony_cideadline_earlier_request(struct request *rq)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	struct rb_node *node = rb_prev(&rq->rb_node);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	if (node)
14062306a36Sopenharmony_ci		return rb_entry_rq(node);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return NULL;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/*
14662306a36Sopenharmony_ci * get the request after `rq' in sector-sorted order
14762306a36Sopenharmony_ci */
14862306a36Sopenharmony_cistatic inline struct request *
14962306a36Sopenharmony_cideadline_latter_request(struct request *rq)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	struct rb_node *node = rb_next(&rq->rb_node);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (node)
15462306a36Sopenharmony_ci		return rb_entry_rq(node);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	return NULL;
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/*
16062306a36Sopenharmony_ci * Return the first request for which blk_rq_pos() >= @pos. For zoned devices,
16162306a36Sopenharmony_ci * return the first request after the start of the zone containing @pos.
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_cistatic inline struct request *deadline_from_pos(struct dd_per_prio *per_prio,
16462306a36Sopenharmony_ci				enum dd_data_dir data_dir, sector_t pos)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct rb_node *node = per_prio->sort_list[data_dir].rb_node;
16762306a36Sopenharmony_ci	struct request *rq, *res = NULL;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	if (!node)
17062306a36Sopenharmony_ci		return NULL;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	rq = rb_entry_rq(node);
17362306a36Sopenharmony_ci	/*
17462306a36Sopenharmony_ci	 * A zoned write may have been requeued with a starting position that
17562306a36Sopenharmony_ci	 * is below that of the most recently dispatched request. Hence, for
17662306a36Sopenharmony_ci	 * zoned writes, start searching from the start of a zone.
17762306a36Sopenharmony_ci	 */
17862306a36Sopenharmony_ci	if (blk_rq_is_seq_zoned_write(rq))
17962306a36Sopenharmony_ci		pos = round_down(pos, rq->q->limits.chunk_sectors);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	while (node) {
18262306a36Sopenharmony_ci		rq = rb_entry_rq(node);
18362306a36Sopenharmony_ci		if (blk_rq_pos(rq) >= pos) {
18462306a36Sopenharmony_ci			res = rq;
18562306a36Sopenharmony_ci			node = node->rb_left;
18662306a36Sopenharmony_ci		} else {
18762306a36Sopenharmony_ci			node = node->rb_right;
18862306a36Sopenharmony_ci		}
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci	return res;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic void
19462306a36Sopenharmony_cideadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	struct rb_root *root = deadline_rb_root(per_prio, rq);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	elv_rb_add(root, rq);
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic inline void
20262306a36Sopenharmony_cideadline_del_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	elv_rb_del(deadline_rb_root(per_prio, rq), rq);
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci/*
20862306a36Sopenharmony_ci * remove rq from rbtree and fifo.
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistatic void deadline_remove_request(struct request_queue *q,
21162306a36Sopenharmony_ci				    struct dd_per_prio *per_prio,
21262306a36Sopenharmony_ci				    struct request *rq)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	list_del_init(&rq->queuelist);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	/*
21762306a36Sopenharmony_ci	 * We might not be on the rbtree, if we are doing an insert merge
21862306a36Sopenharmony_ci	 */
21962306a36Sopenharmony_ci	if (!RB_EMPTY_NODE(&rq->rb_node))
22062306a36Sopenharmony_ci		deadline_del_rq_rb(per_prio, rq);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	elv_rqhash_del(q, rq);
22362306a36Sopenharmony_ci	if (q->last_merge == rq)
22462306a36Sopenharmony_ci		q->last_merge = NULL;
22562306a36Sopenharmony_ci}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic void dd_request_merged(struct request_queue *q, struct request *req,
22862306a36Sopenharmony_ci			      enum elv_merge type)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
23162306a36Sopenharmony_ci	const u8 ioprio_class = dd_rq_ioclass(req);
23262306a36Sopenharmony_ci	const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
23362306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	/*
23662306a36Sopenharmony_ci	 * if the merge was a front merge, we need to reposition request
23762306a36Sopenharmony_ci	 */
23862306a36Sopenharmony_ci	if (type == ELEVATOR_FRONT_MERGE) {
23962306a36Sopenharmony_ci		elv_rb_del(deadline_rb_root(per_prio, req), req);
24062306a36Sopenharmony_ci		deadline_add_rq_rb(per_prio, req);
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci/*
24562306a36Sopenharmony_ci * Callback function that is invoked after @next has been merged into @req.
24662306a36Sopenharmony_ci */
24762306a36Sopenharmony_cistatic void dd_merged_requests(struct request_queue *q, struct request *req,
24862306a36Sopenharmony_ci			       struct request *next)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
25162306a36Sopenharmony_ci	const u8 ioprio_class = dd_rq_ioclass(next);
25262306a36Sopenharmony_ci	const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	lockdep_assert_held(&dd->lock);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	dd->per_prio[prio].stats.merged++;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/*
25962306a36Sopenharmony_ci	 * if next expires before rq, assign its expire time to rq
26062306a36Sopenharmony_ci	 * and move into next position (next will be deleted) in fifo
26162306a36Sopenharmony_ci	 */
26262306a36Sopenharmony_ci	if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
26362306a36Sopenharmony_ci		if (time_before((unsigned long)next->fifo_time,
26462306a36Sopenharmony_ci				(unsigned long)req->fifo_time)) {
26562306a36Sopenharmony_ci			list_move(&req->queuelist, &next->queuelist);
26662306a36Sopenharmony_ci			req->fifo_time = next->fifo_time;
26762306a36Sopenharmony_ci		}
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * kill knowledge of next, this one is a goner
27262306a36Sopenharmony_ci	 */
27362306a36Sopenharmony_ci	deadline_remove_request(q, &dd->per_prio[prio], next);
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci/*
27762306a36Sopenharmony_ci * move an entry to dispatch queue
27862306a36Sopenharmony_ci */
27962306a36Sopenharmony_cistatic void
28062306a36Sopenharmony_cideadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
28162306a36Sopenharmony_ci		      struct request *rq)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	/*
28462306a36Sopenharmony_ci	 * take it off the sort and fifo list
28562306a36Sopenharmony_ci	 */
28662306a36Sopenharmony_ci	deadline_remove_request(rq->q, per_prio, rq);
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci/* Number of requests queued for a given priority level. */
29062306a36Sopenharmony_cistatic u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	const struct io_stats_per_prio *stats = &dd->per_prio[prio].stats;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	lockdep_assert_held(&dd->lock);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return stats->inserted - atomic_read(&stats->completed);
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci/*
30062306a36Sopenharmony_ci * deadline_check_fifo returns true if and only if there are expired requests
30162306a36Sopenharmony_ci * in the FIFO list. Requires !list_empty(&dd->fifo_list[data_dir]).
30262306a36Sopenharmony_ci */
30362306a36Sopenharmony_cistatic inline bool deadline_check_fifo(struct dd_per_prio *per_prio,
30462306a36Sopenharmony_ci				       enum dd_data_dir data_dir)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	struct request *rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	return time_is_before_eq_jiffies((unsigned long)rq->fifo_time);
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci/*
31262306a36Sopenharmony_ci * Check if rq has a sequential request preceding it.
31362306a36Sopenharmony_ci */
31462306a36Sopenharmony_cistatic bool deadline_is_seq_write(struct deadline_data *dd, struct request *rq)
31562306a36Sopenharmony_ci{
31662306a36Sopenharmony_ci	struct request *prev = deadline_earlier_request(rq);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	if (!prev)
31962306a36Sopenharmony_ci		return false;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	return blk_rq_pos(prev) + blk_rq_sectors(prev) == blk_rq_pos(rq);
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci/*
32562306a36Sopenharmony_ci * Skip all write requests that are sequential from @rq, even if we cross
32662306a36Sopenharmony_ci * a zone boundary.
32762306a36Sopenharmony_ci */
32862306a36Sopenharmony_cistatic struct request *deadline_skip_seq_writes(struct deadline_data *dd,
32962306a36Sopenharmony_ci						struct request *rq)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	sector_t pos = blk_rq_pos(rq);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	do {
33462306a36Sopenharmony_ci		pos += blk_rq_sectors(rq);
33562306a36Sopenharmony_ci		rq = deadline_latter_request(rq);
33662306a36Sopenharmony_ci	} while (rq && blk_rq_pos(rq) == pos);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	return rq;
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci/*
34262306a36Sopenharmony_ci * For the specified data direction, return the next request to
34362306a36Sopenharmony_ci * dispatch using arrival ordered lists.
34462306a36Sopenharmony_ci */
34562306a36Sopenharmony_cistatic struct request *
34662306a36Sopenharmony_cideadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
34762306a36Sopenharmony_ci		      enum dd_data_dir data_dir)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	struct request *rq, *rb_rq, *next;
35062306a36Sopenharmony_ci	unsigned long flags;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (list_empty(&per_prio->fifo_list[data_dir]))
35362306a36Sopenharmony_ci		return NULL;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
35662306a36Sopenharmony_ci	if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
35762306a36Sopenharmony_ci		return rq;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	/*
36062306a36Sopenharmony_ci	 * Look for a write request that can be dispatched, that is one with
36162306a36Sopenharmony_ci	 * an unlocked target zone. For some HDDs, breaking a sequential
36262306a36Sopenharmony_ci	 * write stream can lead to lower throughput, so make sure to preserve
36362306a36Sopenharmony_ci	 * sequential write streams, even if that stream crosses into the next
36462306a36Sopenharmony_ci	 * zones and these zones are unlocked.
36562306a36Sopenharmony_ci	 */
36662306a36Sopenharmony_ci	spin_lock_irqsave(&dd->zone_lock, flags);
36762306a36Sopenharmony_ci	list_for_each_entry_safe(rq, next, &per_prio->fifo_list[DD_WRITE],
36862306a36Sopenharmony_ci				 queuelist) {
36962306a36Sopenharmony_ci		/* Check whether a prior request exists for the same zone. */
37062306a36Sopenharmony_ci		rb_rq = deadline_from_pos(per_prio, data_dir, blk_rq_pos(rq));
37162306a36Sopenharmony_ci		if (rb_rq && blk_rq_pos(rb_rq) < blk_rq_pos(rq))
37262306a36Sopenharmony_ci			rq = rb_rq;
37362306a36Sopenharmony_ci		if (blk_req_can_dispatch_to_zone(rq) &&
37462306a36Sopenharmony_ci		    (blk_queue_nonrot(rq->q) ||
37562306a36Sopenharmony_ci		     !deadline_is_seq_write(dd, rq)))
37662306a36Sopenharmony_ci			goto out;
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci	rq = NULL;
37962306a36Sopenharmony_ciout:
38062306a36Sopenharmony_ci	spin_unlock_irqrestore(&dd->zone_lock, flags);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	return rq;
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci/*
38662306a36Sopenharmony_ci * For the specified data direction, return the next request to
38762306a36Sopenharmony_ci * dispatch using sector position sorted lists.
38862306a36Sopenharmony_ci */
38962306a36Sopenharmony_cistatic struct request *
39062306a36Sopenharmony_cideadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
39162306a36Sopenharmony_ci		      enum dd_data_dir data_dir)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	struct request *rq;
39462306a36Sopenharmony_ci	unsigned long flags;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	rq = deadline_from_pos(per_prio, data_dir,
39762306a36Sopenharmony_ci			       per_prio->latest_pos[data_dir]);
39862306a36Sopenharmony_ci	if (!rq)
39962306a36Sopenharmony_ci		return NULL;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
40262306a36Sopenharmony_ci		return rq;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/*
40562306a36Sopenharmony_ci	 * Look for a write request that can be dispatched, that is one with
40662306a36Sopenharmony_ci	 * an unlocked target zone. For some HDDs, breaking a sequential
40762306a36Sopenharmony_ci	 * write stream can lead to lower throughput, so make sure to preserve
40862306a36Sopenharmony_ci	 * sequential write streams, even if that stream crosses into the next
40962306a36Sopenharmony_ci	 * zones and these zones are unlocked.
41062306a36Sopenharmony_ci	 */
41162306a36Sopenharmony_ci	spin_lock_irqsave(&dd->zone_lock, flags);
41262306a36Sopenharmony_ci	while (rq) {
41362306a36Sopenharmony_ci		if (blk_req_can_dispatch_to_zone(rq))
41462306a36Sopenharmony_ci			break;
41562306a36Sopenharmony_ci		if (blk_queue_nonrot(rq->q))
41662306a36Sopenharmony_ci			rq = deadline_latter_request(rq);
41762306a36Sopenharmony_ci		else
41862306a36Sopenharmony_ci			rq = deadline_skip_seq_writes(dd, rq);
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci	spin_unlock_irqrestore(&dd->zone_lock, flags);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	return rq;
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci/*
42662306a36Sopenharmony_ci * Returns true if and only if @rq started after @latest_start where
42762306a36Sopenharmony_ci * @latest_start is in jiffies.
42862306a36Sopenharmony_ci */
42962306a36Sopenharmony_cistatic bool started_after(struct deadline_data *dd, struct request *rq,
43062306a36Sopenharmony_ci			  unsigned long latest_start)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	unsigned long start_time = (unsigned long)rq->fifo_time;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	start_time -= dd->fifo_expire[rq_data_dir(rq)];
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	return time_after(start_time, latest_start);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci/*
44062306a36Sopenharmony_ci * deadline_dispatch_requests selects the best request according to
44162306a36Sopenharmony_ci * read/write expire, fifo_batch, etc and with a start time <= @latest_start.
44262306a36Sopenharmony_ci */
44362306a36Sopenharmony_cistatic struct request *__dd_dispatch_request(struct deadline_data *dd,
44462306a36Sopenharmony_ci					     struct dd_per_prio *per_prio,
44562306a36Sopenharmony_ci					     unsigned long latest_start)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	struct request *rq, *next_rq;
44862306a36Sopenharmony_ci	enum dd_data_dir data_dir;
44962306a36Sopenharmony_ci	enum dd_prio prio;
45062306a36Sopenharmony_ci	u8 ioprio_class;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	lockdep_assert_held(&dd->lock);
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	if (!list_empty(&per_prio->dispatch)) {
45562306a36Sopenharmony_ci		rq = list_first_entry(&per_prio->dispatch, struct request,
45662306a36Sopenharmony_ci				      queuelist);
45762306a36Sopenharmony_ci		if (started_after(dd, rq, latest_start))
45862306a36Sopenharmony_ci			return NULL;
45962306a36Sopenharmony_ci		list_del_init(&rq->queuelist);
46062306a36Sopenharmony_ci		data_dir = rq_data_dir(rq);
46162306a36Sopenharmony_ci		goto done;
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	/*
46562306a36Sopenharmony_ci	 * batches are currently reads XOR writes
46662306a36Sopenharmony_ci	 */
46762306a36Sopenharmony_ci	rq = deadline_next_request(dd, per_prio, dd->last_dir);
46862306a36Sopenharmony_ci	if (rq && dd->batching < dd->fifo_batch) {
46962306a36Sopenharmony_ci		/* we have a next request and are still entitled to batch */
47062306a36Sopenharmony_ci		data_dir = rq_data_dir(rq);
47162306a36Sopenharmony_ci		goto dispatch_request;
47262306a36Sopenharmony_ci	}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	/*
47562306a36Sopenharmony_ci	 * at this point we are not running a batch. select the appropriate
47662306a36Sopenharmony_ci	 * data direction (read / write)
47762306a36Sopenharmony_ci	 */
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (!list_empty(&per_prio->fifo_list[DD_READ])) {
48062306a36Sopenharmony_ci		BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_READ]));
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci		if (deadline_fifo_request(dd, per_prio, DD_WRITE) &&
48362306a36Sopenharmony_ci		    (dd->starved++ >= dd->writes_starved))
48462306a36Sopenharmony_ci			goto dispatch_writes;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci		data_dir = DD_READ;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci		goto dispatch_find_request;
48962306a36Sopenharmony_ci	}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	/*
49262306a36Sopenharmony_ci	 * there are either no reads or writes have been starved
49362306a36Sopenharmony_ci	 */
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (!list_empty(&per_prio->fifo_list[DD_WRITE])) {
49662306a36Sopenharmony_cidispatch_writes:
49762306a36Sopenharmony_ci		BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_WRITE]));
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci		dd->starved = 0;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci		data_dir = DD_WRITE;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci		goto dispatch_find_request;
50462306a36Sopenharmony_ci	}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	return NULL;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_cidispatch_find_request:
50962306a36Sopenharmony_ci	/*
51062306a36Sopenharmony_ci	 * we are not running a batch, find best request for selected data_dir
51162306a36Sopenharmony_ci	 */
51262306a36Sopenharmony_ci	next_rq = deadline_next_request(dd, per_prio, data_dir);
51362306a36Sopenharmony_ci	if (deadline_check_fifo(per_prio, data_dir) || !next_rq) {
51462306a36Sopenharmony_ci		/*
51562306a36Sopenharmony_ci		 * A deadline has expired, the last request was in the other
51662306a36Sopenharmony_ci		 * direction, or we have run out of higher-sectored requests.
51762306a36Sopenharmony_ci		 * Start again from the request with the earliest expiry time.
51862306a36Sopenharmony_ci		 */
51962306a36Sopenharmony_ci		rq = deadline_fifo_request(dd, per_prio, data_dir);
52062306a36Sopenharmony_ci	} else {
52162306a36Sopenharmony_ci		/*
52262306a36Sopenharmony_ci		 * The last req was the same dir and we have a next request in
52362306a36Sopenharmony_ci		 * sort order. No expired requests so continue on from here.
52462306a36Sopenharmony_ci		 */
52562306a36Sopenharmony_ci		rq = next_rq;
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	/*
52962306a36Sopenharmony_ci	 * For a zoned block device, if we only have writes queued and none of
53062306a36Sopenharmony_ci	 * them can be dispatched, rq will be NULL.
53162306a36Sopenharmony_ci	 */
53262306a36Sopenharmony_ci	if (!rq)
53362306a36Sopenharmony_ci		return NULL;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	dd->last_dir = data_dir;
53662306a36Sopenharmony_ci	dd->batching = 0;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_cidispatch_request:
53962306a36Sopenharmony_ci	if (started_after(dd, rq, latest_start))
54062306a36Sopenharmony_ci		return NULL;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	/*
54362306a36Sopenharmony_ci	 * rq is the selected appropriate request.
54462306a36Sopenharmony_ci	 */
54562306a36Sopenharmony_ci	dd->batching++;
54662306a36Sopenharmony_ci	deadline_move_request(dd, per_prio, rq);
54762306a36Sopenharmony_cidone:
54862306a36Sopenharmony_ci	ioprio_class = dd_rq_ioclass(rq);
54962306a36Sopenharmony_ci	prio = ioprio_class_to_prio[ioprio_class];
55062306a36Sopenharmony_ci	dd->per_prio[prio].latest_pos[data_dir] = blk_rq_pos(rq);
55162306a36Sopenharmony_ci	dd->per_prio[prio].stats.dispatched++;
55262306a36Sopenharmony_ci	/*
55362306a36Sopenharmony_ci	 * If the request needs its target zone locked, do it.
55462306a36Sopenharmony_ci	 */
55562306a36Sopenharmony_ci	blk_req_zone_write_lock(rq);
55662306a36Sopenharmony_ci	rq->rq_flags |= RQF_STARTED;
55762306a36Sopenharmony_ci	return rq;
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci/*
56162306a36Sopenharmony_ci * Check whether there are any requests with priority other than DD_RT_PRIO
56262306a36Sopenharmony_ci * that were inserted more than prio_aging_expire jiffies ago.
56362306a36Sopenharmony_ci */
56462306a36Sopenharmony_cistatic struct request *dd_dispatch_prio_aged_requests(struct deadline_data *dd,
56562306a36Sopenharmony_ci						      unsigned long now)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct request *rq;
56862306a36Sopenharmony_ci	enum dd_prio prio;
56962306a36Sopenharmony_ci	int prio_cnt;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	lockdep_assert_held(&dd->lock);
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	prio_cnt = !!dd_queued(dd, DD_RT_PRIO) + !!dd_queued(dd, DD_BE_PRIO) +
57462306a36Sopenharmony_ci		   !!dd_queued(dd, DD_IDLE_PRIO);
57562306a36Sopenharmony_ci	if (prio_cnt < 2)
57662306a36Sopenharmony_ci		return NULL;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	for (prio = DD_BE_PRIO; prio <= DD_PRIO_MAX; prio++) {
57962306a36Sopenharmony_ci		rq = __dd_dispatch_request(dd, &dd->per_prio[prio],
58062306a36Sopenharmony_ci					   now - dd->prio_aging_expire);
58162306a36Sopenharmony_ci		if (rq)
58262306a36Sopenharmony_ci			return rq;
58362306a36Sopenharmony_ci	}
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	return NULL;
58662306a36Sopenharmony_ci}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci/*
58962306a36Sopenharmony_ci * Called from blk_mq_run_hw_queue() -> __blk_mq_sched_dispatch_requests().
59062306a36Sopenharmony_ci *
59162306a36Sopenharmony_ci * One confusing aspect here is that we get called for a specific
59262306a36Sopenharmony_ci * hardware queue, but we may return a request that is for a
59362306a36Sopenharmony_ci * different hardware queue. This is because mq-deadline has shared
59462306a36Sopenharmony_ci * state for all hardware queues, in terms of sorting, FIFOs, etc.
59562306a36Sopenharmony_ci */
59662306a36Sopenharmony_cistatic struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
59762306a36Sopenharmony_ci{
59862306a36Sopenharmony_ci	struct deadline_data *dd = hctx->queue->elevator->elevator_data;
59962306a36Sopenharmony_ci	const unsigned long now = jiffies;
60062306a36Sopenharmony_ci	struct request *rq;
60162306a36Sopenharmony_ci	enum dd_prio prio;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	spin_lock(&dd->lock);
60462306a36Sopenharmony_ci	rq = dd_dispatch_prio_aged_requests(dd, now);
60562306a36Sopenharmony_ci	if (rq)
60662306a36Sopenharmony_ci		goto unlock;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	/*
60962306a36Sopenharmony_ci	 * Next, dispatch requests in priority order. Ignore lower priority
61062306a36Sopenharmony_ci	 * requests if any higher priority requests are pending.
61162306a36Sopenharmony_ci	 */
61262306a36Sopenharmony_ci	for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
61362306a36Sopenharmony_ci		rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now);
61462306a36Sopenharmony_ci		if (rq || dd_queued(dd, prio))
61562306a36Sopenharmony_ci			break;
61662306a36Sopenharmony_ci	}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ciunlock:
61962306a36Sopenharmony_ci	spin_unlock(&dd->lock);
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	return rq;
62262306a36Sopenharmony_ci}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci/*
62562306a36Sopenharmony_ci * Called by __blk_mq_alloc_request(). The shallow_depth value set by this
62662306a36Sopenharmony_ci * function is used by __blk_mq_get_tag().
62762306a36Sopenharmony_ci */
62862306a36Sopenharmony_cistatic void dd_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	struct deadline_data *dd = data->q->elevator->elevator_data;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	/* Do not throttle synchronous reads. */
63362306a36Sopenharmony_ci	if (op_is_sync(opf) && !op_is_write(opf))
63462306a36Sopenharmony_ci		return;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	/*
63762306a36Sopenharmony_ci	 * Throttle asynchronous requests and writes such that these requests
63862306a36Sopenharmony_ci	 * do not block the allocation of synchronous requests.
63962306a36Sopenharmony_ci	 */
64062306a36Sopenharmony_ci	data->shallow_depth = dd->async_depth;
64162306a36Sopenharmony_ci}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci/* Called by blk_mq_update_nr_requests(). */
64462306a36Sopenharmony_cistatic void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
64562306a36Sopenharmony_ci{
64662306a36Sopenharmony_ci	struct request_queue *q = hctx->queue;
64762306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
64862306a36Sopenharmony_ci	struct blk_mq_tags *tags = hctx->sched_tags;
64962306a36Sopenharmony_ci	unsigned int shift = tags->bitmap_tags.sb.shift;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	dd->async_depth = max(1U, 3 * (1U << shift)  / 4);
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, dd->async_depth);
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci/* Called by blk_mq_init_hctx() and blk_mq_init_sched(). */
65762306a36Sopenharmony_cistatic int dd_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
65862306a36Sopenharmony_ci{
65962306a36Sopenharmony_ci	dd_depth_updated(hctx);
66062306a36Sopenharmony_ci	return 0;
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_cistatic void dd_exit_sched(struct elevator_queue *e)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	struct deadline_data *dd = e->elevator_data;
66662306a36Sopenharmony_ci	enum dd_prio prio;
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
66962306a36Sopenharmony_ci		struct dd_per_prio *per_prio = &dd->per_prio[prio];
67062306a36Sopenharmony_ci		const struct io_stats_per_prio *stats = &per_prio->stats;
67162306a36Sopenharmony_ci		uint32_t queued;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci		WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_READ]));
67462306a36Sopenharmony_ci		WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_WRITE]));
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci		spin_lock(&dd->lock);
67762306a36Sopenharmony_ci		queued = dd_queued(dd, prio);
67862306a36Sopenharmony_ci		spin_unlock(&dd->lock);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci		WARN_ONCE(queued != 0,
68162306a36Sopenharmony_ci			  "statistics for priority %d: i %u m %u d %u c %u\n",
68262306a36Sopenharmony_ci			  prio, stats->inserted, stats->merged,
68362306a36Sopenharmony_ci			  stats->dispatched, atomic_read(&stats->completed));
68462306a36Sopenharmony_ci	}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	kfree(dd);
68762306a36Sopenharmony_ci}
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci/*
69062306a36Sopenharmony_ci * initialize elevator private data (deadline_data).
69162306a36Sopenharmony_ci */
69262306a36Sopenharmony_cistatic int dd_init_sched(struct request_queue *q, struct elevator_type *e)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	struct deadline_data *dd;
69562306a36Sopenharmony_ci	struct elevator_queue *eq;
69662306a36Sopenharmony_ci	enum dd_prio prio;
69762306a36Sopenharmony_ci	int ret = -ENOMEM;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	eq = elevator_alloc(q, e);
70062306a36Sopenharmony_ci	if (!eq)
70162306a36Sopenharmony_ci		return ret;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
70462306a36Sopenharmony_ci	if (!dd)
70562306a36Sopenharmony_ci		goto put_eq;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	eq->elevator_data = dd;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
71062306a36Sopenharmony_ci		struct dd_per_prio *per_prio = &dd->per_prio[prio];
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci		INIT_LIST_HEAD(&per_prio->dispatch);
71362306a36Sopenharmony_ci		INIT_LIST_HEAD(&per_prio->fifo_list[DD_READ]);
71462306a36Sopenharmony_ci		INIT_LIST_HEAD(&per_prio->fifo_list[DD_WRITE]);
71562306a36Sopenharmony_ci		per_prio->sort_list[DD_READ] = RB_ROOT;
71662306a36Sopenharmony_ci		per_prio->sort_list[DD_WRITE] = RB_ROOT;
71762306a36Sopenharmony_ci	}
71862306a36Sopenharmony_ci	dd->fifo_expire[DD_READ] = read_expire;
71962306a36Sopenharmony_ci	dd->fifo_expire[DD_WRITE] = write_expire;
72062306a36Sopenharmony_ci	dd->writes_starved = writes_starved;
72162306a36Sopenharmony_ci	dd->front_merges = 1;
72262306a36Sopenharmony_ci	dd->last_dir = DD_WRITE;
72362306a36Sopenharmony_ci	dd->fifo_batch = fifo_batch;
72462306a36Sopenharmony_ci	dd->prio_aging_expire = prio_aging_expire;
72562306a36Sopenharmony_ci	spin_lock_init(&dd->lock);
72662306a36Sopenharmony_ci	spin_lock_init(&dd->zone_lock);
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	/* We dispatch from request queue wide instead of hw queue */
72962306a36Sopenharmony_ci	blk_queue_flag_set(QUEUE_FLAG_SQ_SCHED, q);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	q->elevator = eq;
73262306a36Sopenharmony_ci	return 0;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ciput_eq:
73562306a36Sopenharmony_ci	kobject_put(&eq->kobj);
73662306a36Sopenharmony_ci	return ret;
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci/*
74062306a36Sopenharmony_ci * Try to merge @bio into an existing request. If @bio has been merged into
74162306a36Sopenharmony_ci * an existing request, store the pointer to that request into *@rq.
74262306a36Sopenharmony_ci */
74362306a36Sopenharmony_cistatic int dd_request_merge(struct request_queue *q, struct request **rq,
74462306a36Sopenharmony_ci			    struct bio *bio)
74562306a36Sopenharmony_ci{
74662306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
74762306a36Sopenharmony_ci	const u8 ioprio_class = IOPRIO_PRIO_CLASS(bio->bi_ioprio);
74862306a36Sopenharmony_ci	const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
74962306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];
75062306a36Sopenharmony_ci	sector_t sector = bio_end_sector(bio);
75162306a36Sopenharmony_ci	struct request *__rq;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	if (!dd->front_merges)
75462306a36Sopenharmony_ci		return ELEVATOR_NO_MERGE;
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	__rq = elv_rb_find(&per_prio->sort_list[bio_data_dir(bio)], sector);
75762306a36Sopenharmony_ci	if (__rq) {
75862306a36Sopenharmony_ci		BUG_ON(sector != blk_rq_pos(__rq));
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci		if (elv_bio_merge_ok(__rq, bio)) {
76162306a36Sopenharmony_ci			*rq = __rq;
76262306a36Sopenharmony_ci			if (blk_discard_mergable(__rq))
76362306a36Sopenharmony_ci				return ELEVATOR_DISCARD_MERGE;
76462306a36Sopenharmony_ci			return ELEVATOR_FRONT_MERGE;
76562306a36Sopenharmony_ci		}
76662306a36Sopenharmony_ci	}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return ELEVATOR_NO_MERGE;
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci/*
77262306a36Sopenharmony_ci * Attempt to merge a bio into an existing request. This function is called
77362306a36Sopenharmony_ci * before @bio is associated with a request.
77462306a36Sopenharmony_ci */
77562306a36Sopenharmony_cistatic bool dd_bio_merge(struct request_queue *q, struct bio *bio,
77662306a36Sopenharmony_ci		unsigned int nr_segs)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
77962306a36Sopenharmony_ci	struct request *free = NULL;
78062306a36Sopenharmony_ci	bool ret;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	spin_lock(&dd->lock);
78362306a36Sopenharmony_ci	ret = blk_mq_sched_try_merge(q, bio, nr_segs, &free);
78462306a36Sopenharmony_ci	spin_unlock(&dd->lock);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	if (free)
78762306a36Sopenharmony_ci		blk_mq_free_request(free);
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	return ret;
79062306a36Sopenharmony_ci}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci/*
79362306a36Sopenharmony_ci * add rq to rbtree and fifo
79462306a36Sopenharmony_ci */
79562306a36Sopenharmony_cistatic void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
79662306a36Sopenharmony_ci			      blk_insert_t flags, struct list_head *free)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	struct request_queue *q = hctx->queue;
79962306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
80062306a36Sopenharmony_ci	const enum dd_data_dir data_dir = rq_data_dir(rq);
80162306a36Sopenharmony_ci	u16 ioprio = req_get_ioprio(rq);
80262306a36Sopenharmony_ci	u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio);
80362306a36Sopenharmony_ci	struct dd_per_prio *per_prio;
80462306a36Sopenharmony_ci	enum dd_prio prio;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	lockdep_assert_held(&dd->lock);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	/*
80962306a36Sopenharmony_ci	 * This may be a requeue of a write request that has locked its
81062306a36Sopenharmony_ci	 * target zone. If it is the case, this releases the zone lock.
81162306a36Sopenharmony_ci	 */
81262306a36Sopenharmony_ci	blk_req_zone_write_unlock(rq);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	prio = ioprio_class_to_prio[ioprio_class];
81562306a36Sopenharmony_ci	per_prio = &dd->per_prio[prio];
81662306a36Sopenharmony_ci	if (!rq->elv.priv[0]) {
81762306a36Sopenharmony_ci		per_prio->stats.inserted++;
81862306a36Sopenharmony_ci		rq->elv.priv[0] = (void *)(uintptr_t)1;
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	if (blk_mq_sched_try_insert_merge(q, rq, free))
82262306a36Sopenharmony_ci		return;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	trace_block_rq_insert(rq);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	if (flags & BLK_MQ_INSERT_AT_HEAD) {
82762306a36Sopenharmony_ci		list_add(&rq->queuelist, &per_prio->dispatch);
82862306a36Sopenharmony_ci		rq->fifo_time = jiffies;
82962306a36Sopenharmony_ci	} else {
83062306a36Sopenharmony_ci		struct list_head *insert_before;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		deadline_add_rq_rb(per_prio, rq);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci		if (rq_mergeable(rq)) {
83562306a36Sopenharmony_ci			elv_rqhash_add(q, rq);
83662306a36Sopenharmony_ci			if (!q->last_merge)
83762306a36Sopenharmony_ci				q->last_merge = rq;
83862306a36Sopenharmony_ci		}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci		/*
84162306a36Sopenharmony_ci		 * set expire time and add to fifo list
84262306a36Sopenharmony_ci		 */
84362306a36Sopenharmony_ci		rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
84462306a36Sopenharmony_ci		insert_before = &per_prio->fifo_list[data_dir];
84562306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED
84662306a36Sopenharmony_ci		/*
84762306a36Sopenharmony_ci		 * Insert zoned writes such that requests are sorted by
84862306a36Sopenharmony_ci		 * position per zone.
84962306a36Sopenharmony_ci		 */
85062306a36Sopenharmony_ci		if (blk_rq_is_seq_zoned_write(rq)) {
85162306a36Sopenharmony_ci			struct request *rq2 = deadline_latter_request(rq);
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci			if (rq2 && blk_rq_zone_no(rq2) == blk_rq_zone_no(rq))
85462306a36Sopenharmony_ci				insert_before = &rq2->queuelist;
85562306a36Sopenharmony_ci		}
85662306a36Sopenharmony_ci#endif
85762306a36Sopenharmony_ci		list_add_tail(&rq->queuelist, insert_before);
85862306a36Sopenharmony_ci	}
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci/*
86262306a36Sopenharmony_ci * Called from blk_mq_insert_request() or blk_mq_dispatch_plug_list().
86362306a36Sopenharmony_ci */
86462306a36Sopenharmony_cistatic void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
86562306a36Sopenharmony_ci			       struct list_head *list,
86662306a36Sopenharmony_ci			       blk_insert_t flags)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	struct request_queue *q = hctx->queue;
86962306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
87062306a36Sopenharmony_ci	LIST_HEAD(free);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	spin_lock(&dd->lock);
87362306a36Sopenharmony_ci	while (!list_empty(list)) {
87462306a36Sopenharmony_ci		struct request *rq;
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci		rq = list_first_entry(list, struct request, queuelist);
87762306a36Sopenharmony_ci		list_del_init(&rq->queuelist);
87862306a36Sopenharmony_ci		dd_insert_request(hctx, rq, flags, &free);
87962306a36Sopenharmony_ci	}
88062306a36Sopenharmony_ci	spin_unlock(&dd->lock);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	blk_mq_free_requests(&free);
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci/* Callback from inside blk_mq_rq_ctx_init(). */
88662306a36Sopenharmony_cistatic void dd_prepare_request(struct request *rq)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	rq->elv.priv[0] = NULL;
88962306a36Sopenharmony_ci}
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cistatic bool dd_has_write_work(struct blk_mq_hw_ctx *hctx)
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci	struct deadline_data *dd = hctx->queue->elevator->elevator_data;
89462306a36Sopenharmony_ci	enum dd_prio p;
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	for (p = 0; p <= DD_PRIO_MAX; p++)
89762306a36Sopenharmony_ci		if (!list_empty_careful(&dd->per_prio[p].fifo_list[DD_WRITE]))
89862306a36Sopenharmony_ci			return true;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	return false;
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci/*
90462306a36Sopenharmony_ci * Callback from inside blk_mq_free_request().
90562306a36Sopenharmony_ci *
90662306a36Sopenharmony_ci * For zoned block devices, write unlock the target zone of
90762306a36Sopenharmony_ci * completed write requests. Do this while holding the zone lock
90862306a36Sopenharmony_ci * spinlock so that the zone is never unlocked while deadline_fifo_request()
90962306a36Sopenharmony_ci * or deadline_next_request() are executing. This function is called for
91062306a36Sopenharmony_ci * all requests, whether or not these requests complete successfully.
91162306a36Sopenharmony_ci *
91262306a36Sopenharmony_ci * For a zoned block device, __dd_dispatch_request() may have stopped
91362306a36Sopenharmony_ci * dispatching requests if all the queued requests are write requests directed
91462306a36Sopenharmony_ci * at zones that are already locked due to on-going write requests. To ensure
91562306a36Sopenharmony_ci * write request dispatch progress in this case, mark the queue as needing a
91662306a36Sopenharmony_ci * restart to ensure that the queue is run again after completion of the
91762306a36Sopenharmony_ci * request and zones being unlocked.
91862306a36Sopenharmony_ci */
91962306a36Sopenharmony_cistatic void dd_finish_request(struct request *rq)
92062306a36Sopenharmony_ci{
92162306a36Sopenharmony_ci	struct request_queue *q = rq->q;
92262306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
92362306a36Sopenharmony_ci	const u8 ioprio_class = dd_rq_ioclass(rq);
92462306a36Sopenharmony_ci	const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
92562306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	/*
92862306a36Sopenharmony_ci	 * The block layer core may call dd_finish_request() without having
92962306a36Sopenharmony_ci	 * called dd_insert_requests(). Skip requests that bypassed I/O
93062306a36Sopenharmony_ci	 * scheduling. See also blk_mq_request_bypass_insert().
93162306a36Sopenharmony_ci	 */
93262306a36Sopenharmony_ci	if (!rq->elv.priv[0])
93362306a36Sopenharmony_ci		return;
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	atomic_inc(&per_prio->stats.completed);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	if (blk_queue_is_zoned(q)) {
93862306a36Sopenharmony_ci		unsigned long flags;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci		spin_lock_irqsave(&dd->zone_lock, flags);
94162306a36Sopenharmony_ci		blk_req_zone_write_unlock(rq);
94262306a36Sopenharmony_ci		spin_unlock_irqrestore(&dd->zone_lock, flags);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci		if (dd_has_write_work(rq->mq_hctx))
94562306a36Sopenharmony_ci			blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
94662306a36Sopenharmony_ci	}
94762306a36Sopenharmony_ci}
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_cistatic bool dd_has_work_for_prio(struct dd_per_prio *per_prio)
95062306a36Sopenharmony_ci{
95162306a36Sopenharmony_ci	return !list_empty_careful(&per_prio->dispatch) ||
95262306a36Sopenharmony_ci		!list_empty_careful(&per_prio->fifo_list[DD_READ]) ||
95362306a36Sopenharmony_ci		!list_empty_careful(&per_prio->fifo_list[DD_WRITE]);
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_cistatic bool dd_has_work(struct blk_mq_hw_ctx *hctx)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	struct deadline_data *dd = hctx->queue->elevator->elevator_data;
95962306a36Sopenharmony_ci	enum dd_prio prio;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	for (prio = 0; prio <= DD_PRIO_MAX; prio++)
96262306a36Sopenharmony_ci		if (dd_has_work_for_prio(&dd->per_prio[prio]))
96362306a36Sopenharmony_ci			return true;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	return false;
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci/*
96962306a36Sopenharmony_ci * sysfs parts below
97062306a36Sopenharmony_ci */
97162306a36Sopenharmony_ci#define SHOW_INT(__FUNC, __VAR)						\
97262306a36Sopenharmony_cistatic ssize_t __FUNC(struct elevator_queue *e, char *page)		\
97362306a36Sopenharmony_ci{									\
97462306a36Sopenharmony_ci	struct deadline_data *dd = e->elevator_data;			\
97562306a36Sopenharmony_ci									\
97662306a36Sopenharmony_ci	return sysfs_emit(page, "%d\n", __VAR);				\
97762306a36Sopenharmony_ci}
97862306a36Sopenharmony_ci#define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR))
97962306a36Sopenharmony_ciSHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]);
98062306a36Sopenharmony_ciSHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
98162306a36Sopenharmony_ciSHOW_JIFFIES(deadline_prio_aging_expire_show, dd->prio_aging_expire);
98262306a36Sopenharmony_ciSHOW_INT(deadline_writes_starved_show, dd->writes_starved);
98362306a36Sopenharmony_ciSHOW_INT(deadline_front_merges_show, dd->front_merges);
98462306a36Sopenharmony_ciSHOW_INT(deadline_async_depth_show, dd->async_depth);
98562306a36Sopenharmony_ciSHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
98662306a36Sopenharmony_ci#undef SHOW_INT
98762306a36Sopenharmony_ci#undef SHOW_JIFFIES
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
99062306a36Sopenharmony_cistatic ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)	\
99162306a36Sopenharmony_ci{									\
99262306a36Sopenharmony_ci	struct deadline_data *dd = e->elevator_data;			\
99362306a36Sopenharmony_ci	int __data, __ret;						\
99462306a36Sopenharmony_ci									\
99562306a36Sopenharmony_ci	__ret = kstrtoint(page, 0, &__data);				\
99662306a36Sopenharmony_ci	if (__ret < 0)							\
99762306a36Sopenharmony_ci		return __ret;						\
99862306a36Sopenharmony_ci	if (__data < (MIN))						\
99962306a36Sopenharmony_ci		__data = (MIN);						\
100062306a36Sopenharmony_ci	else if (__data > (MAX))					\
100162306a36Sopenharmony_ci		__data = (MAX);						\
100262306a36Sopenharmony_ci	*(__PTR) = __CONV(__data);					\
100362306a36Sopenharmony_ci	return count;							\
100462306a36Sopenharmony_ci}
100562306a36Sopenharmony_ci#define STORE_INT(__FUNC, __PTR, MIN, MAX)				\
100662306a36Sopenharmony_ci	STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, )
100762306a36Sopenharmony_ci#define STORE_JIFFIES(__FUNC, __PTR, MIN, MAX)				\
100862306a36Sopenharmony_ci	STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies)
100962306a36Sopenharmony_ciSTORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX);
101062306a36Sopenharmony_ciSTORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX);
101162306a36Sopenharmony_ciSTORE_JIFFIES(deadline_prio_aging_expire_store, &dd->prio_aging_expire, 0, INT_MAX);
101262306a36Sopenharmony_ciSTORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
101362306a36Sopenharmony_ciSTORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
101462306a36Sopenharmony_ciSTORE_INT(deadline_async_depth_store, &dd->async_depth, 1, INT_MAX);
101562306a36Sopenharmony_ciSTORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
101662306a36Sopenharmony_ci#undef STORE_FUNCTION
101762306a36Sopenharmony_ci#undef STORE_INT
101862306a36Sopenharmony_ci#undef STORE_JIFFIES
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci#define DD_ATTR(name) \
102162306a36Sopenharmony_ci	__ATTR(name, 0644, deadline_##name##_show, deadline_##name##_store)
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_cistatic struct elv_fs_entry deadline_attrs[] = {
102462306a36Sopenharmony_ci	DD_ATTR(read_expire),
102562306a36Sopenharmony_ci	DD_ATTR(write_expire),
102662306a36Sopenharmony_ci	DD_ATTR(writes_starved),
102762306a36Sopenharmony_ci	DD_ATTR(front_merges),
102862306a36Sopenharmony_ci	DD_ATTR(async_depth),
102962306a36Sopenharmony_ci	DD_ATTR(fifo_batch),
103062306a36Sopenharmony_ci	DD_ATTR(prio_aging_expire),
103162306a36Sopenharmony_ci	__ATTR_NULL
103262306a36Sopenharmony_ci};
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEBUG_FS
103562306a36Sopenharmony_ci#define DEADLINE_DEBUGFS_DDIR_ATTRS(prio, data_dir, name)		\
103662306a36Sopenharmony_cistatic void *deadline_##name##_fifo_start(struct seq_file *m,		\
103762306a36Sopenharmony_ci					  loff_t *pos)			\
103862306a36Sopenharmony_ci	__acquires(&dd->lock)						\
103962306a36Sopenharmony_ci{									\
104062306a36Sopenharmony_ci	struct request_queue *q = m->private;				\
104162306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
104262306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];		\
104362306a36Sopenharmony_ci									\
104462306a36Sopenharmony_ci	spin_lock(&dd->lock);						\
104562306a36Sopenharmony_ci	return seq_list_start(&per_prio->fifo_list[data_dir], *pos);	\
104662306a36Sopenharmony_ci}									\
104762306a36Sopenharmony_ci									\
104862306a36Sopenharmony_cistatic void *deadline_##name##_fifo_next(struct seq_file *m, void *v,	\
104962306a36Sopenharmony_ci					 loff_t *pos)			\
105062306a36Sopenharmony_ci{									\
105162306a36Sopenharmony_ci	struct request_queue *q = m->private;				\
105262306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
105362306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];		\
105462306a36Sopenharmony_ci									\
105562306a36Sopenharmony_ci	return seq_list_next(v, &per_prio->fifo_list[data_dir], pos);	\
105662306a36Sopenharmony_ci}									\
105762306a36Sopenharmony_ci									\
105862306a36Sopenharmony_cistatic void deadline_##name##_fifo_stop(struct seq_file *m, void *v)	\
105962306a36Sopenharmony_ci	__releases(&dd->lock)						\
106062306a36Sopenharmony_ci{									\
106162306a36Sopenharmony_ci	struct request_queue *q = m->private;				\
106262306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
106362306a36Sopenharmony_ci									\
106462306a36Sopenharmony_ci	spin_unlock(&dd->lock);						\
106562306a36Sopenharmony_ci}									\
106662306a36Sopenharmony_ci									\
106762306a36Sopenharmony_cistatic const struct seq_operations deadline_##name##_fifo_seq_ops = {	\
106862306a36Sopenharmony_ci	.start	= deadline_##name##_fifo_start,				\
106962306a36Sopenharmony_ci	.next	= deadline_##name##_fifo_next,				\
107062306a36Sopenharmony_ci	.stop	= deadline_##name##_fifo_stop,				\
107162306a36Sopenharmony_ci	.show	= blk_mq_debugfs_rq_show,				\
107262306a36Sopenharmony_ci};									\
107362306a36Sopenharmony_ci									\
107462306a36Sopenharmony_cistatic int deadline_##name##_next_rq_show(void *data,			\
107562306a36Sopenharmony_ci					  struct seq_file *m)		\
107662306a36Sopenharmony_ci{									\
107762306a36Sopenharmony_ci	struct request_queue *q = data;					\
107862306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
107962306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];		\
108062306a36Sopenharmony_ci	struct request *rq;						\
108162306a36Sopenharmony_ci									\
108262306a36Sopenharmony_ci	rq = deadline_from_pos(per_prio, data_dir,			\
108362306a36Sopenharmony_ci			       per_prio->latest_pos[data_dir]);		\
108462306a36Sopenharmony_ci	if (rq)								\
108562306a36Sopenharmony_ci		__blk_mq_debugfs_rq_show(m, rq);			\
108662306a36Sopenharmony_ci	return 0;							\
108762306a36Sopenharmony_ci}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ciDEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_READ, read0);
109062306a36Sopenharmony_ciDEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_WRITE, write0);
109162306a36Sopenharmony_ciDEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_READ, read1);
109262306a36Sopenharmony_ciDEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_WRITE, write1);
109362306a36Sopenharmony_ciDEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_READ, read2);
109462306a36Sopenharmony_ciDEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_WRITE, write2);
109562306a36Sopenharmony_ci#undef DEADLINE_DEBUGFS_DDIR_ATTRS
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_cistatic int deadline_batching_show(void *data, struct seq_file *m)
109862306a36Sopenharmony_ci{
109962306a36Sopenharmony_ci	struct request_queue *q = data;
110062306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	seq_printf(m, "%u\n", dd->batching);
110362306a36Sopenharmony_ci	return 0;
110462306a36Sopenharmony_ci}
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_cistatic int deadline_starved_show(void *data, struct seq_file *m)
110762306a36Sopenharmony_ci{
110862306a36Sopenharmony_ci	struct request_queue *q = data;
110962306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	seq_printf(m, "%u\n", dd->starved);
111262306a36Sopenharmony_ci	return 0;
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic int dd_async_depth_show(void *data, struct seq_file *m)
111662306a36Sopenharmony_ci{
111762306a36Sopenharmony_ci	struct request_queue *q = data;
111862306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	seq_printf(m, "%u\n", dd->async_depth);
112162306a36Sopenharmony_ci	return 0;
112262306a36Sopenharmony_ci}
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_cistatic int dd_queued_show(void *data, struct seq_file *m)
112562306a36Sopenharmony_ci{
112662306a36Sopenharmony_ci	struct request_queue *q = data;
112762306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
112862306a36Sopenharmony_ci	u32 rt, be, idle;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	spin_lock(&dd->lock);
113162306a36Sopenharmony_ci	rt = dd_queued(dd, DD_RT_PRIO);
113262306a36Sopenharmony_ci	be = dd_queued(dd, DD_BE_PRIO);
113362306a36Sopenharmony_ci	idle = dd_queued(dd, DD_IDLE_PRIO);
113462306a36Sopenharmony_ci	spin_unlock(&dd->lock);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	seq_printf(m, "%u %u %u\n", rt, be, idle);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	return 0;
113962306a36Sopenharmony_ci}
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci/* Number of requests owned by the block driver for a given priority. */
114262306a36Sopenharmony_cistatic u32 dd_owned_by_driver(struct deadline_data *dd, enum dd_prio prio)
114362306a36Sopenharmony_ci{
114462306a36Sopenharmony_ci	const struct io_stats_per_prio *stats = &dd->per_prio[prio].stats;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	lockdep_assert_held(&dd->lock);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	return stats->dispatched + stats->merged -
114962306a36Sopenharmony_ci		atomic_read(&stats->completed);
115062306a36Sopenharmony_ci}
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_cistatic int dd_owned_by_driver_show(void *data, struct seq_file *m)
115362306a36Sopenharmony_ci{
115462306a36Sopenharmony_ci	struct request_queue *q = data;
115562306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;
115662306a36Sopenharmony_ci	u32 rt, be, idle;
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	spin_lock(&dd->lock);
115962306a36Sopenharmony_ci	rt = dd_owned_by_driver(dd, DD_RT_PRIO);
116062306a36Sopenharmony_ci	be = dd_owned_by_driver(dd, DD_BE_PRIO);
116162306a36Sopenharmony_ci	idle = dd_owned_by_driver(dd, DD_IDLE_PRIO);
116262306a36Sopenharmony_ci	spin_unlock(&dd->lock);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	seq_printf(m, "%u %u %u\n", rt, be, idle);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	return 0;
116762306a36Sopenharmony_ci}
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci#define DEADLINE_DISPATCH_ATTR(prio)					\
117062306a36Sopenharmony_cistatic void *deadline_dispatch##prio##_start(struct seq_file *m,	\
117162306a36Sopenharmony_ci					     loff_t *pos)		\
117262306a36Sopenharmony_ci	__acquires(&dd->lock)						\
117362306a36Sopenharmony_ci{									\
117462306a36Sopenharmony_ci	struct request_queue *q = m->private;				\
117562306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
117662306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];		\
117762306a36Sopenharmony_ci									\
117862306a36Sopenharmony_ci	spin_lock(&dd->lock);						\
117962306a36Sopenharmony_ci	return seq_list_start(&per_prio->dispatch, *pos);		\
118062306a36Sopenharmony_ci}									\
118162306a36Sopenharmony_ci									\
118262306a36Sopenharmony_cistatic void *deadline_dispatch##prio##_next(struct seq_file *m,		\
118362306a36Sopenharmony_ci					    void *v, loff_t *pos)	\
118462306a36Sopenharmony_ci{									\
118562306a36Sopenharmony_ci	struct request_queue *q = m->private;				\
118662306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
118762306a36Sopenharmony_ci	struct dd_per_prio *per_prio = &dd->per_prio[prio];		\
118862306a36Sopenharmony_ci									\
118962306a36Sopenharmony_ci	return seq_list_next(v, &per_prio->dispatch, pos);		\
119062306a36Sopenharmony_ci}									\
119162306a36Sopenharmony_ci									\
119262306a36Sopenharmony_cistatic void deadline_dispatch##prio##_stop(struct seq_file *m, void *v)	\
119362306a36Sopenharmony_ci	__releases(&dd->lock)						\
119462306a36Sopenharmony_ci{									\
119562306a36Sopenharmony_ci	struct request_queue *q = m->private;				\
119662306a36Sopenharmony_ci	struct deadline_data *dd = q->elevator->elevator_data;		\
119762306a36Sopenharmony_ci									\
119862306a36Sopenharmony_ci	spin_unlock(&dd->lock);						\
119962306a36Sopenharmony_ci}									\
120062306a36Sopenharmony_ci									\
120162306a36Sopenharmony_cistatic const struct seq_operations deadline_dispatch##prio##_seq_ops = { \
120262306a36Sopenharmony_ci	.start	= deadline_dispatch##prio##_start,			\
120362306a36Sopenharmony_ci	.next	= deadline_dispatch##prio##_next,			\
120462306a36Sopenharmony_ci	.stop	= deadline_dispatch##prio##_stop,			\
120562306a36Sopenharmony_ci	.show	= blk_mq_debugfs_rq_show,				\
120662306a36Sopenharmony_ci}
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ciDEADLINE_DISPATCH_ATTR(0);
120962306a36Sopenharmony_ciDEADLINE_DISPATCH_ATTR(1);
121062306a36Sopenharmony_ciDEADLINE_DISPATCH_ATTR(2);
121162306a36Sopenharmony_ci#undef DEADLINE_DISPATCH_ATTR
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci#define DEADLINE_QUEUE_DDIR_ATTRS(name)					\
121462306a36Sopenharmony_ci	{#name "_fifo_list", 0400,					\
121562306a36Sopenharmony_ci			.seq_ops = &deadline_##name##_fifo_seq_ops}
121662306a36Sopenharmony_ci#define DEADLINE_NEXT_RQ_ATTR(name)					\
121762306a36Sopenharmony_ci	{#name "_next_rq", 0400, deadline_##name##_next_rq_show}
121862306a36Sopenharmony_cistatic const struct blk_mq_debugfs_attr deadline_queue_debugfs_attrs[] = {
121962306a36Sopenharmony_ci	DEADLINE_QUEUE_DDIR_ATTRS(read0),
122062306a36Sopenharmony_ci	DEADLINE_QUEUE_DDIR_ATTRS(write0),
122162306a36Sopenharmony_ci	DEADLINE_QUEUE_DDIR_ATTRS(read1),
122262306a36Sopenharmony_ci	DEADLINE_QUEUE_DDIR_ATTRS(write1),
122362306a36Sopenharmony_ci	DEADLINE_QUEUE_DDIR_ATTRS(read2),
122462306a36Sopenharmony_ci	DEADLINE_QUEUE_DDIR_ATTRS(write2),
122562306a36Sopenharmony_ci	DEADLINE_NEXT_RQ_ATTR(read0),
122662306a36Sopenharmony_ci	DEADLINE_NEXT_RQ_ATTR(write0),
122762306a36Sopenharmony_ci	DEADLINE_NEXT_RQ_ATTR(read1),
122862306a36Sopenharmony_ci	DEADLINE_NEXT_RQ_ATTR(write1),
122962306a36Sopenharmony_ci	DEADLINE_NEXT_RQ_ATTR(read2),
123062306a36Sopenharmony_ci	DEADLINE_NEXT_RQ_ATTR(write2),
123162306a36Sopenharmony_ci	{"batching", 0400, deadline_batching_show},
123262306a36Sopenharmony_ci	{"starved", 0400, deadline_starved_show},
123362306a36Sopenharmony_ci	{"async_depth", 0400, dd_async_depth_show},
123462306a36Sopenharmony_ci	{"dispatch0", 0400, .seq_ops = &deadline_dispatch0_seq_ops},
123562306a36Sopenharmony_ci	{"dispatch1", 0400, .seq_ops = &deadline_dispatch1_seq_ops},
123662306a36Sopenharmony_ci	{"dispatch2", 0400, .seq_ops = &deadline_dispatch2_seq_ops},
123762306a36Sopenharmony_ci	{"owned_by_driver", 0400, dd_owned_by_driver_show},
123862306a36Sopenharmony_ci	{"queued", 0400, dd_queued_show},
123962306a36Sopenharmony_ci	{},
124062306a36Sopenharmony_ci};
124162306a36Sopenharmony_ci#undef DEADLINE_QUEUE_DDIR_ATTRS
124262306a36Sopenharmony_ci#endif
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_cistatic struct elevator_type mq_deadline = {
124562306a36Sopenharmony_ci	.ops = {
124662306a36Sopenharmony_ci		.depth_updated		= dd_depth_updated,
124762306a36Sopenharmony_ci		.limit_depth		= dd_limit_depth,
124862306a36Sopenharmony_ci		.insert_requests	= dd_insert_requests,
124962306a36Sopenharmony_ci		.dispatch_request	= dd_dispatch_request,
125062306a36Sopenharmony_ci		.prepare_request	= dd_prepare_request,
125162306a36Sopenharmony_ci		.finish_request		= dd_finish_request,
125262306a36Sopenharmony_ci		.next_request		= elv_rb_latter_request,
125362306a36Sopenharmony_ci		.former_request		= elv_rb_former_request,
125462306a36Sopenharmony_ci		.bio_merge		= dd_bio_merge,
125562306a36Sopenharmony_ci		.request_merge		= dd_request_merge,
125662306a36Sopenharmony_ci		.requests_merged	= dd_merged_requests,
125762306a36Sopenharmony_ci		.request_merged		= dd_request_merged,
125862306a36Sopenharmony_ci		.has_work		= dd_has_work,
125962306a36Sopenharmony_ci		.init_sched		= dd_init_sched,
126062306a36Sopenharmony_ci		.exit_sched		= dd_exit_sched,
126162306a36Sopenharmony_ci		.init_hctx		= dd_init_hctx,
126262306a36Sopenharmony_ci	},
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEBUG_FS
126562306a36Sopenharmony_ci	.queue_debugfs_attrs = deadline_queue_debugfs_attrs,
126662306a36Sopenharmony_ci#endif
126762306a36Sopenharmony_ci	.elevator_attrs = deadline_attrs,
126862306a36Sopenharmony_ci	.elevator_name = "mq-deadline",
126962306a36Sopenharmony_ci	.elevator_alias = "deadline",
127062306a36Sopenharmony_ci	.elevator_features = ELEVATOR_F_ZBD_SEQ_WRITE,
127162306a36Sopenharmony_ci	.elevator_owner = THIS_MODULE,
127262306a36Sopenharmony_ci};
127362306a36Sopenharmony_ciMODULE_ALIAS("mq-deadline-iosched");
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cistatic int __init deadline_init(void)
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	return elv_register(&mq_deadline);
127862306a36Sopenharmony_ci}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_cistatic void __exit deadline_exit(void)
128162306a36Sopenharmony_ci{
128262306a36Sopenharmony_ci	elv_unregister(&mq_deadline);
128362306a36Sopenharmony_ci}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_cimodule_init(deadline_init);
128662306a36Sopenharmony_cimodule_exit(deadline_exit);
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ciMODULE_AUTHOR("Jens Axboe, Damien Le Moal and Bart Van Assche");
128962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
129062306a36Sopenharmony_ciMODULE_DESCRIPTION("MQ deadline IO scheduler");
1291