xref: /linux/drivers/md/dm-vdo/vio.h (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
19533d804SMatthew Sakai /* SPDX-License-Identifier: GPL-2.0-only */
29533d804SMatthew Sakai /*
39533d804SMatthew Sakai  * Copyright 2023 Red Hat
49533d804SMatthew Sakai  */
59533d804SMatthew Sakai 
69533d804SMatthew Sakai #ifndef VIO_H
79533d804SMatthew Sakai #define VIO_H
89533d804SMatthew Sakai 
99533d804SMatthew Sakai #include <linux/bio.h>
109533d804SMatthew Sakai #include <linux/blkdev.h>
119533d804SMatthew Sakai #include <linux/compiler.h>
129533d804SMatthew Sakai #include <linux/kernel.h>
139533d804SMatthew Sakai #include <linux/list.h>
149533d804SMatthew Sakai 
159533d804SMatthew Sakai #include "completion.h"
169533d804SMatthew Sakai #include "constants.h"
179533d804SMatthew Sakai #include "types.h"
189533d804SMatthew Sakai #include "vdo.h"
199533d804SMatthew Sakai 
209533d804SMatthew Sakai enum {
219533d804SMatthew Sakai 	MAX_BLOCKS_PER_VIO = (BIO_MAX_VECS << PAGE_SHIFT) / VDO_BLOCK_SIZE,
229533d804SMatthew Sakai };
239533d804SMatthew Sakai 
249533d804SMatthew Sakai struct pooled_vio {
259533d804SMatthew Sakai 	/* The underlying vio */
269533d804SMatthew Sakai 	struct vio vio;
279533d804SMatthew Sakai 	/* The list entry for chaining pooled vios together */
289533d804SMatthew Sakai 	struct list_head list_entry;
299533d804SMatthew Sakai 	/* The context set by the pool */
309533d804SMatthew Sakai 	void *context;
319533d804SMatthew Sakai 	/* The list entry used by the pool */
329533d804SMatthew Sakai 	struct list_head pool_entry;
339533d804SMatthew Sakai };
349533d804SMatthew Sakai 
359533d804SMatthew Sakai /**
369533d804SMatthew Sakai  * as_vio() - Convert a generic vdo_completion to a vio.
379533d804SMatthew Sakai  * @completion: The completion to convert.
389533d804SMatthew Sakai  *
399533d804SMatthew Sakai  * Return: The completion as a vio.
409533d804SMatthew Sakai  */
as_vio(struct vdo_completion * completion)419533d804SMatthew Sakai static inline struct vio *as_vio(struct vdo_completion *completion)
429533d804SMatthew Sakai {
439533d804SMatthew Sakai 	vdo_assert_completion_type(completion, VIO_COMPLETION);
449533d804SMatthew Sakai 	return container_of(completion, struct vio, completion);
459533d804SMatthew Sakai }
469533d804SMatthew Sakai 
479533d804SMatthew Sakai /**
489533d804SMatthew Sakai  * get_vio_bio_zone_thread_id() - Get the thread id of the bio zone in which a vio should submit
499533d804SMatthew Sakai  *                                its I/O.
509533d804SMatthew Sakai  * @vio: The vio.
519533d804SMatthew Sakai  *
529533d804SMatthew Sakai  * Return: The id of the bio zone thread the vio should use.
539533d804SMatthew Sakai  */
get_vio_bio_zone_thread_id(struct vio * vio)549533d804SMatthew Sakai static inline thread_id_t __must_check get_vio_bio_zone_thread_id(struct vio *vio)
559533d804SMatthew Sakai {
569533d804SMatthew Sakai 	return vio->completion.vdo->thread_config.bio_threads[vio->bio_zone];
579533d804SMatthew Sakai }
589533d804SMatthew Sakai 
599533d804SMatthew Sakai physical_block_number_t __must_check pbn_from_vio_bio(struct bio *bio);
609533d804SMatthew Sakai 
619533d804SMatthew Sakai /**
629533d804SMatthew Sakai  * assert_vio_in_bio_zone() - Check that a vio is running on the correct thread for its bio zone.
639533d804SMatthew Sakai  * @vio: The vio to check.
649533d804SMatthew Sakai  */
assert_vio_in_bio_zone(struct vio * vio)659533d804SMatthew Sakai static inline void assert_vio_in_bio_zone(struct vio *vio)
669533d804SMatthew Sakai {
679533d804SMatthew Sakai 	thread_id_t expected = get_vio_bio_zone_thread_id(vio);
689533d804SMatthew Sakai 	thread_id_t thread_id = vdo_get_callback_thread_id();
699533d804SMatthew Sakai 
70*6a79248bSMike Snitzer 	VDO_ASSERT_LOG_ONLY((expected == thread_id),
719533d804SMatthew Sakai 			    "vio I/O for physical block %llu on thread %u, should be on bio zone thread %u",
729533d804SMatthew Sakai 			    (unsigned long long) pbn_from_vio_bio(vio->bio), thread_id,
739533d804SMatthew Sakai 			    expected);
749533d804SMatthew Sakai }
759533d804SMatthew Sakai 
769533d804SMatthew Sakai int vdo_create_bio(struct bio **bio_ptr);
779533d804SMatthew Sakai void vdo_free_bio(struct bio *bio);
789533d804SMatthew Sakai int allocate_vio_components(struct vdo *vdo, enum vio_type vio_type,
799533d804SMatthew Sakai 			    enum vio_priority priority, void *parent,
809533d804SMatthew Sakai 			    unsigned int block_count, char *data, struct vio *vio);
819533d804SMatthew Sakai int __must_check create_multi_block_metadata_vio(struct vdo *vdo, enum vio_type vio_type,
829533d804SMatthew Sakai 						 enum vio_priority priority,
839533d804SMatthew Sakai 						 void *parent, unsigned int block_count,
849533d804SMatthew Sakai 						 char *data, struct vio **vio_ptr);
859533d804SMatthew Sakai 
create_metadata_vio(struct vdo * vdo,enum vio_type vio_type,enum vio_priority priority,void * parent,char * data,struct vio ** vio_ptr)869533d804SMatthew Sakai static inline int __must_check create_metadata_vio(struct vdo *vdo, enum vio_type vio_type,
879533d804SMatthew Sakai 						   enum vio_priority priority,
889533d804SMatthew Sakai 						   void *parent, char *data,
899533d804SMatthew Sakai 						   struct vio **vio_ptr)
909533d804SMatthew Sakai {
919533d804SMatthew Sakai 	return create_multi_block_metadata_vio(vdo, vio_type, priority, parent, 1, data,
929533d804SMatthew Sakai 					       vio_ptr);
939533d804SMatthew Sakai }
949533d804SMatthew Sakai 
959533d804SMatthew Sakai void free_vio_components(struct vio *vio);
969533d804SMatthew Sakai void free_vio(struct vio *vio);
979533d804SMatthew Sakai 
989533d804SMatthew Sakai /**
999533d804SMatthew Sakai  * initialize_vio() - Initialize a vio.
1009533d804SMatthew Sakai  * @vio: The vio to initialize.
1019533d804SMatthew Sakai  * @bio: The bio this vio should use for its I/O.
1029533d804SMatthew Sakai  * @block_count: The size of this vio in vdo blocks.
1039533d804SMatthew Sakai  * @vio_type: The vio type.
1049533d804SMatthew Sakai  * @priority: The relative priority of the vio.
1059533d804SMatthew Sakai  * @vdo: The vdo for this vio.
1069533d804SMatthew Sakai  */
initialize_vio(struct vio * vio,struct bio * bio,unsigned int block_count,enum vio_type vio_type,enum vio_priority priority,struct vdo * vdo)1079533d804SMatthew Sakai static inline void initialize_vio(struct vio *vio, struct bio *bio,
1089533d804SMatthew Sakai 				  unsigned int block_count, enum vio_type vio_type,
1099533d804SMatthew Sakai 				  enum vio_priority priority, struct vdo *vdo)
1109533d804SMatthew Sakai {
1119533d804SMatthew Sakai 	/* data_vio's may not span multiple blocks */
1129533d804SMatthew Sakai 	BUG_ON((vio_type == VIO_TYPE_DATA) && (block_count != 1));
1139533d804SMatthew Sakai 
1149533d804SMatthew Sakai 	vio->bio = bio;
1159533d804SMatthew Sakai 	vio->block_count = block_count;
1169533d804SMatthew Sakai 	vio->type = vio_type;
1179533d804SMatthew Sakai 	vio->priority = priority;
1189533d804SMatthew Sakai 	vdo_initialize_completion(&vio->completion, vdo, VIO_COMPLETION);
1199533d804SMatthew Sakai }
1209533d804SMatthew Sakai 
1219533d804SMatthew Sakai void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callback,
122a6c05c98SMike Snitzer 			    blk_opf_t bi_opf, physical_block_number_t pbn);
1239533d804SMatthew Sakai 
1249533d804SMatthew Sakai int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
125a6c05c98SMike Snitzer 		  blk_opf_t bi_opf, physical_block_number_t pbn);
1269533d804SMatthew Sakai 
1279533d804SMatthew Sakai void update_vio_error_stats(struct vio *vio, const char *format, ...)
1289533d804SMatthew Sakai 	__printf(2, 3);
1299533d804SMatthew Sakai 
1309533d804SMatthew Sakai /**
1319533d804SMatthew Sakai  * is_data_vio() - Check whether a vio is servicing an external data request.
1329533d804SMatthew Sakai  * @vio: The vio to check.
1339533d804SMatthew Sakai  */
is_data_vio(struct vio * vio)1349533d804SMatthew Sakai static inline bool is_data_vio(struct vio *vio)
1359533d804SMatthew Sakai {
1369533d804SMatthew Sakai 	return (vio->type == VIO_TYPE_DATA);
1379533d804SMatthew Sakai }
1389533d804SMatthew Sakai 
1399533d804SMatthew Sakai /**
1409533d804SMatthew Sakai  * get_metadata_priority() - Convert a vio's priority to a work item priority.
1419533d804SMatthew Sakai  * @vio: The vio.
1429533d804SMatthew Sakai  *
1439533d804SMatthew Sakai  * Return: The priority with which to submit the vio's bio.
1449533d804SMatthew Sakai  */
get_metadata_priority(struct vio * vio)1459533d804SMatthew Sakai static inline enum vdo_completion_priority get_metadata_priority(struct vio *vio)
1469533d804SMatthew Sakai {
1479533d804SMatthew Sakai 	return ((vio->priority == VIO_PRIORITY_HIGH) ?
1489533d804SMatthew Sakai 		BIO_Q_HIGH_PRIORITY :
1499533d804SMatthew Sakai 		BIO_Q_METADATA_PRIORITY);
1509533d804SMatthew Sakai }
1519533d804SMatthew Sakai 
1529533d804SMatthew Sakai /**
1539533d804SMatthew Sakai  * continue_vio() - Enqueue a vio to run its next callback.
1549533d804SMatthew Sakai  * @vio: The vio to continue.
1559533d804SMatthew Sakai  *
1569533d804SMatthew Sakai  * Return: The result of the current operation.
1579533d804SMatthew Sakai  */
continue_vio(struct vio * vio,int result)1589533d804SMatthew Sakai static inline void continue_vio(struct vio *vio, int result)
1599533d804SMatthew Sakai {
1609533d804SMatthew Sakai 	if (unlikely(result != VDO_SUCCESS))
1619533d804SMatthew Sakai 		vdo_set_completion_result(&vio->completion, result);
1629533d804SMatthew Sakai 
1639533d804SMatthew Sakai 	vdo_enqueue_completion(&vio->completion, VDO_WORK_Q_DEFAULT_PRIORITY);
1649533d804SMatthew Sakai }
1659533d804SMatthew Sakai 
1669533d804SMatthew Sakai void vdo_count_bios(struct atomic_bio_stats *bio_stats, struct bio *bio);
1679533d804SMatthew Sakai void vdo_count_completed_bios(struct bio *bio);
1689533d804SMatthew Sakai 
1699533d804SMatthew Sakai /**
1709533d804SMatthew Sakai  * continue_vio_after_io() - Continue a vio now that its I/O has returned.
1719533d804SMatthew Sakai  */
continue_vio_after_io(struct vio * vio,vdo_action_fn callback,thread_id_t thread)1729533d804SMatthew Sakai static inline void continue_vio_after_io(struct vio *vio, vdo_action_fn callback,
1739533d804SMatthew Sakai 					 thread_id_t thread)
1749533d804SMatthew Sakai {
1759533d804SMatthew Sakai 	vdo_count_completed_bios(vio->bio);
1769533d804SMatthew Sakai 	vdo_set_completion_callback(&vio->completion, callback, thread);
1779533d804SMatthew Sakai 	continue_vio(vio, blk_status_to_errno(vio->bio->bi_status));
1789533d804SMatthew Sakai }
1799533d804SMatthew Sakai 
1809533d804SMatthew Sakai void vio_record_metadata_io_error(struct vio *vio);
1819533d804SMatthew Sakai 
1829533d804SMatthew Sakai /* A vio_pool is a collection of preallocated vios used to write arbitrary metadata blocks. */
1839533d804SMatthew Sakai 
vio_as_pooled_vio(struct vio * vio)1849533d804SMatthew Sakai static inline struct pooled_vio *vio_as_pooled_vio(struct vio *vio)
1859533d804SMatthew Sakai {
1869533d804SMatthew Sakai 	return container_of(vio, struct pooled_vio, vio);
1879533d804SMatthew Sakai }
1889533d804SMatthew Sakai 
1899533d804SMatthew Sakai struct vio_pool;
1909533d804SMatthew Sakai 
1919533d804SMatthew Sakai int __must_check make_vio_pool(struct vdo *vdo, size_t pool_size, thread_id_t thread_id,
1929533d804SMatthew Sakai 			       enum vio_type vio_type, enum vio_priority priority,
1939533d804SMatthew Sakai 			       void *context, struct vio_pool **pool_ptr);
1949533d804SMatthew Sakai void free_vio_pool(struct vio_pool *pool);
1959533d804SMatthew Sakai bool __must_check is_vio_pool_busy(struct vio_pool *pool);
196d6e260ccSMike Snitzer void acquire_vio_from_pool(struct vio_pool *pool, struct vdo_waiter *waiter);
1979533d804SMatthew Sakai void return_vio_to_pool(struct vio_pool *pool, struct pooled_vio *vio);
1989533d804SMatthew Sakai 
1999533d804SMatthew Sakai #endif /* VIO_H */
200