xref: /linux/include/linux/blk_plug.h (revision 55ab7e14222e5f0b0fd9f7711ca391d2924b35e3)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_BLK_PLUG_H
3 #define _LINUX_BLK_PLUG_H
4 
5 #include <linux/sched.h>
6 
7 struct blk_plug_cb;
8 typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *cb, bool from_schedule);
9 
10 struct rq_list {
11 	struct request *head;
12 	struct request *tail;
13 };
14 
15 #ifdef CONFIG_BLOCK
16 /*
17  * blk_plug permits building a queue of related requests by holding the I/O
18  * fragments for a short period. This allows merging of sequential requests
19  * into single larger request. As the requests are moved from a per-task list to
20  * the device's request_queue in a batch, this results in improved scalability
21  * as the lock contention for request_queue lock is reduced.
22  *
23  * It is ok not to disable preemption when adding the request to the plug list
24  * or when attempting a merge. For details, please see schedule() where
25  * blk_flush_plug() is called.
26  */
27 struct blk_plug {
28 	struct rq_list mq_list; /* blk-mq requests */
29 
30 	/* if ios_left is > 1, we can batch tag/rq allocations */
31 	struct rq_list cached_rqs;
32 	u64 cur_ktime;
33 	unsigned short nr_ios;
34 
35 	unsigned short rq_count;
36 
37 	bool multiple_queues;
38 	bool has_elevator;
39 
40 	struct list_head cb_list; /* md requires an unplug callback */
41 };
42 
43 void blk_start_plug(struct blk_plug *);
44 void blk_start_plug_nr_ios(struct blk_plug *, unsigned short);
45 void blk_finish_plug(struct blk_plug *);
46 
47 void __blk_flush_plug(struct blk_plug *plug, bool from_schedule);
blk_flush_plug(struct blk_plug * plug,bool async)48 static inline void blk_flush_plug(struct blk_plug *plug, bool async)
49 {
50 	if (plug)
51 		__blk_flush_plug(plug, async);
52 }
53 
blk_plug_invalidate_ts(void)54 static __always_inline void blk_plug_invalidate_ts(void)
55 {
56 	if (unlikely(current->flags & PF_BLOCK_TS)) {
57 		current->plug->cur_ktime = 0;
58 		current->flags &= ~PF_BLOCK_TS;
59 	}
60 }
61 
62 struct blk_plug_cb {
63 	struct list_head list;
64 	blk_plug_cb_fn callback;
65 	void *data;
66 };
67 
68 struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug, void *data,
69 		int size);
70 #else /* CONFIG_BLOCK */
71 struct blk_plug {
72 };
73 
blk_start_plug(struct blk_plug * plug)74 static inline void blk_start_plug(struct blk_plug *plug)
75 {
76 }
77 
blk_start_plug_nr_ios(struct blk_plug * plug,unsigned short nr_ios)78 static inline void blk_start_plug_nr_ios(struct blk_plug *plug,
79 					 unsigned short nr_ios)
80 {
81 }
82 
blk_finish_plug(struct blk_plug * plug)83 static inline void blk_finish_plug(struct blk_plug *plug)
84 {
85 }
86 
blk_flush_plug(struct blk_plug * plug,bool async)87 static inline void blk_flush_plug(struct blk_plug *plug, bool async)
88 {
89 }
90 
blk_plug_invalidate_ts(void)91 static inline void blk_plug_invalidate_ts(void)
92 {
93 }
94 #endif /* CONFIG_BLOCK */
95 #endif /* _LINUX_BLK_PLUG_H */
96