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 */ 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 */ 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 */ 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 709533d804SMatthew Sakai 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 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 */ 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, 1229533d804SMatthew Sakai unsigned int 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, 1259533d804SMatthew Sakai unsigned int 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 */ 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 */ 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 */ 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 */ 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 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); 196*d6e260ccSMike 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