diff options
Diffstat (limited to 'include/linux/blk_plug.h')
| -rw-r--r-- | include/linux/blk_plug.h | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/include/linux/blk_plug.h b/include/linux/blk_plug.h new file mode 100644 index 000000000000..2ac1265662ad --- /dev/null +++ b/include/linux/blk_plug.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_BLK_PLUG_H +#define _LINUX_BLK_PLUG_H + +#include <linux/sched.h> + +struct blk_plug_cb; +typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *cb, bool from_schedule); + +struct rq_list { + struct request *head; + struct request *tail; +}; + +#ifdef CONFIG_BLOCK +/* + * blk_plug permits building a queue of related requests by holding the I/O + * fragments for a short period. This allows merging of sequential requests + * into single larger request. As the requests are moved from a per-task list to + * the device's request_queue in a batch, this results in improved scalability + * as the lock contention for request_queue lock is reduced. + * + * It is ok not to disable preemption when adding the request to the plug list + * or when attempting a merge. For details, please see schedule() where + * blk_flush_plug() is called. + */ +struct blk_plug { + struct rq_list mq_list; /* blk-mq requests */ + + /* if ios_left is > 1, we can batch tag/rq allocations */ + struct rq_list cached_rqs; + u64 cur_ktime; + unsigned short nr_ios; + + unsigned short rq_count; + + bool multiple_queues; + bool has_elevator; + + struct list_head cb_list; /* md requires an unplug callback */ +}; + +void blk_start_plug(struct blk_plug *); +void blk_start_plug_nr_ios(struct blk_plug *, unsigned short); +void blk_finish_plug(struct blk_plug *); + +void __blk_flush_plug(struct blk_plug *plug, bool from_schedule); +static inline void blk_flush_plug(struct blk_plug *plug, bool async) +{ + if (plug) + __blk_flush_plug(plug, async); +} + +static __always_inline void blk_plug_invalidate_ts(void) +{ + if (unlikely(current->flags & PF_BLOCK_TS)) { + current->plug->cur_ktime = 0; + current->flags &= ~PF_BLOCK_TS; + } +} + +struct blk_plug_cb { + struct list_head list; + blk_plug_cb_fn callback; + void *data; +}; + +struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug, void *data, + int size); +#else /* CONFIG_BLOCK */ +struct blk_plug { +}; + +static inline void blk_start_plug(struct blk_plug *plug) +{ +} + +static inline void blk_start_plug_nr_ios(struct blk_plug *plug, + unsigned short nr_ios) +{ +} + +static inline void blk_finish_plug(struct blk_plug *plug) +{ +} + +static inline void blk_flush_plug(struct blk_plug *plug, bool async) +{ +} + +static inline void blk_plug_invalidate_ts(void) +{ +} +#endif /* CONFIG_BLOCK */ +#endif /* _LINUX_BLK_PLUG_H */ |
