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