1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _ELEVATOR_H
3  #define _ELEVATOR_H
4  
5  #include <linux/percpu.h>
6  #include <linux/hashtable.h>
7  #include "blk-mq.h"
8  
9  struct io_cq;
10  struct elevator_type;
11  struct blk_mq_debugfs_attr;
12  
13  /*
14   * Return values from elevator merger
15   */
16  enum elv_merge {
17  	ELEVATOR_NO_MERGE	= 0,
18  	ELEVATOR_FRONT_MERGE	= 1,
19  	ELEVATOR_BACK_MERGE	= 2,
20  	ELEVATOR_DISCARD_MERGE	= 3,
21  };
22  
23  struct blk_mq_alloc_data;
24  struct blk_mq_hw_ctx;
25  
26  struct elevator_mq_ops {
27  	int (*init_sched)(struct request_queue *, struct elevator_type *);
28  	void (*exit_sched)(struct elevator_queue *);
29  	int (*init_hctx)(struct blk_mq_hw_ctx *, unsigned int);
30  	void (*exit_hctx)(struct blk_mq_hw_ctx *, unsigned int);
31  	void (*depth_updated)(struct blk_mq_hw_ctx *);
32  
33  	bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
34  	bool (*bio_merge)(struct request_queue *, struct bio *, unsigned int);
35  	int (*request_merge)(struct request_queue *q, struct request **, struct bio *);
36  	void (*request_merged)(struct request_queue *, struct request *, enum elv_merge);
37  	void (*requests_merged)(struct request_queue *, struct request *, struct request *);
38  	void (*limit_depth)(blk_opf_t, struct blk_mq_alloc_data *);
39  	void (*prepare_request)(struct request *);
40  	void (*finish_request)(struct request *);
41  	void (*insert_requests)(struct blk_mq_hw_ctx *hctx, struct list_head *list,
42  			blk_insert_t flags);
43  	struct request *(*dispatch_request)(struct blk_mq_hw_ctx *);
44  	bool (*has_work)(struct blk_mq_hw_ctx *);
45  	void (*completed_request)(struct request *, u64);
46  	void (*requeue_request)(struct request *);
47  	struct request *(*former_request)(struct request_queue *, struct request *);
48  	struct request *(*next_request)(struct request_queue *, struct request *);
49  	void (*init_icq)(struct io_cq *);
50  	void (*exit_icq)(struct io_cq *);
51  };
52  
53  #define ELV_NAME_MAX	(16)
54  
55  struct elv_fs_entry {
56  	struct attribute attr;
57  	ssize_t (*show)(struct elevator_queue *, char *);
58  	ssize_t (*store)(struct elevator_queue *, const char *, size_t);
59  };
60  
61  /*
62   * identifies an elevator type, such as AS or deadline
63   */
64  struct elevator_type
65  {
66  	/* managed by elevator core */
67  	struct kmem_cache *icq_cache;
68  
69  	/* fields provided by elevator implementation */
70  	struct elevator_mq_ops ops;
71  
72  	size_t icq_size;	/* see iocontext.h */
73  	size_t icq_align;	/* ditto */
74  	struct elv_fs_entry *elevator_attrs;
75  	const char *elevator_name;
76  	const char *elevator_alias;
77  	struct module *elevator_owner;
78  #ifdef CONFIG_BLK_DEBUG_FS
79  	const struct blk_mq_debugfs_attr *queue_debugfs_attrs;
80  	const struct blk_mq_debugfs_attr *hctx_debugfs_attrs;
81  #endif
82  
83  	/* managed by elevator core */
84  	char icq_cache_name[ELV_NAME_MAX + 6];	/* elvname + "_io_cq" */
85  	struct list_head list;
86  };
87  
elevator_tryget(struct elevator_type * e)88  static inline bool elevator_tryget(struct elevator_type *e)
89  {
90  	return try_module_get(e->elevator_owner);
91  }
92  
__elevator_get(struct elevator_type * e)93  static inline void __elevator_get(struct elevator_type *e)
94  {
95  	__module_get(e->elevator_owner);
96  }
97  
elevator_put(struct elevator_type * e)98  static inline void elevator_put(struct elevator_type *e)
99  {
100  	module_put(e->elevator_owner);
101  }
102  
103  #define ELV_HASH_BITS 6
104  
105  void elv_rqhash_del(struct request_queue *q, struct request *rq);
106  void elv_rqhash_add(struct request_queue *q, struct request *rq);
107  void elv_rqhash_reposition(struct request_queue *q, struct request *rq);
108  struct request *elv_rqhash_find(struct request_queue *q, sector_t offset);
109  
110  /*
111   * each queue has an elevator_queue associated with it
112   */
113  struct elevator_queue
114  {
115  	struct elevator_type *type;
116  	void *elevator_data;
117  	struct kobject kobj;
118  	struct mutex sysfs_lock;
119  	unsigned long flags;
120  	DECLARE_HASHTABLE(hash, ELV_HASH_BITS);
121  };
122  
123  #define ELEVATOR_FLAG_REGISTERED	0
124  #define ELEVATOR_FLAG_DISABLE_WBT	1
125  
126  /*
127   * block elevator interface
128   */
129  extern enum elv_merge elv_merge(struct request_queue *, struct request **,
130  		struct bio *);
131  extern void elv_merge_requests(struct request_queue *, struct request *,
132  			       struct request *);
133  extern void elv_merged_request(struct request_queue *, struct request *,
134  		enum elv_merge);
135  extern bool elv_attempt_insert_merge(struct request_queue *, struct request *,
136  				     struct list_head *);
137  extern struct request *elv_former_request(struct request_queue *, struct request *);
138  extern struct request *elv_latter_request(struct request_queue *, struct request *);
139  void elevator_init_mq(struct request_queue *q);
140  
141  /*
142   * io scheduler registration
143   */
144  extern int elv_register(struct elevator_type *);
145  extern void elv_unregister(struct elevator_type *);
146  
147  /*
148   * io scheduler sysfs switching
149   */
150  ssize_t elv_iosched_show(struct gendisk *disk, char *page);
151  int elv_iosched_load_module(struct gendisk *disk, const char *page,
152  			    size_t count);
153  ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count);
154  
155  extern bool elv_bio_merge_ok(struct request *, struct bio *);
156  extern struct elevator_queue *elevator_alloc(struct request_queue *,
157  					struct elevator_type *);
158  
159  /*
160   * Helper functions.
161   */
162  extern struct request *elv_rb_former_request(struct request_queue *, struct request *);
163  extern struct request *elv_rb_latter_request(struct request_queue *, struct request *);
164  
165  /*
166   * rb support functions.
167   */
168  extern void elv_rb_add(struct rb_root *, struct request *);
169  extern void elv_rb_del(struct rb_root *, struct request *);
170  extern struct request *elv_rb_find(struct rb_root *, sector_t);
171  
172  /*
173   * Insertion selection
174   */
175  #define ELEVATOR_INSERT_FRONT	1
176  #define ELEVATOR_INSERT_BACK	2
177  #define ELEVATOR_INSERT_SORT	3
178  #define ELEVATOR_INSERT_REQUEUE	4
179  #define ELEVATOR_INSERT_FLUSH	5
180  #define ELEVATOR_INSERT_SORT_MERGE	6
181  
182  #define rb_entry_rq(node)	rb_entry((node), struct request, rb_node)
183  
184  #define rq_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
185  #define rq_fifo_clear(rq)	list_del_init(&(rq)->queuelist)
186  
187  #endif /* _ELEVATOR_H */
188