1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright 2023 Red Hat 4 */ 5 6 #ifndef VDO_PACKER_H 7 #define VDO_PACKER_H 8 9 #include <linux/list.h> 10 11 #include "admin-state.h" 12 #include "constants.h" 13 #include "encodings.h" 14 #include "statistics.h" 15 #include "types.h" 16 #include "wait-queue.h" 17 18 enum { 19 DEFAULT_PACKER_BINS = 16, 20 }; 21 22 /* The header of a compressed block. */ 23 struct compressed_block_header { 24 /* Unsigned 32-bit major and minor versions, little-endian */ 25 struct packed_version_number version; 26 27 /* List of unsigned 16-bit compressed block sizes, little-endian */ 28 __le16 sizes[VDO_MAX_COMPRESSION_SLOTS]; 29 } __packed; 30 31 enum { 32 VDO_COMPRESSED_BLOCK_DATA_SIZE = VDO_BLOCK_SIZE - sizeof(struct compressed_block_header), 33 34 /* 35 * A compressed block is only written if we can pack at least two fragments into it, so a 36 * fragment which fills the entire data portion of a compressed block is too big. 37 */ 38 VDO_MAX_COMPRESSED_FRAGMENT_SIZE = VDO_COMPRESSED_BLOCK_DATA_SIZE - 1, 39 }; 40 41 /* * The compressed block overlay. */ 42 struct compressed_block { 43 struct compressed_block_header header; 44 char data[VDO_COMPRESSED_BLOCK_DATA_SIZE]; 45 } __packed; 46 47 /* 48 * Each packer_bin holds an incomplete batch of data_vios that only partially fill a compressed 49 * block. The bins are kept in a ring sorted by the amount of unused space so the first bin with 50 * enough space to hold a newly-compressed data_vio can easily be found. When the bin fills up or 51 * is flushed, the first uncanceled data_vio in the bin is selected to be the agent for that bin. 52 * Upon entering the packer, each data_vio already has its compressed data in the first slot of the 53 * data_vio's compressed_block (overlaid on the data_vio's scratch_block). So the agent's fragment 54 * is already in place. The fragments for the other uncanceled data_vios in the bin are packed into 55 * the agent's compressed block. The agent then writes out the compressed block. If the write is 56 * successful, the agent shares its pbn lock which each of the other data_vios in its compressed 57 * block and sends each on its way. Finally the agent itself continues on the write path as before. 58 * 59 * There is one special bin which is used to hold data_vios which have been canceled and removed 60 * from their bin by the packer. These data_vios need to wait for the canceller to rendezvous with 61 * them and so they sit in this special bin. 62 */ 63 struct packer_bin { 64 /* List links for packer.packer_bins */ 65 struct list_head list; 66 /* The number of items in the bin */ 67 slot_number_t slots_used; 68 /* The number of compressed block bytes remaining in the current batch */ 69 size_t free_space; 70 /* The current partial batch of data_vios, waiting for more */ 71 struct data_vio *incoming[]; 72 }; 73 74 struct packer { 75 /* The ID of the packer's callback thread */ 76 thread_id_t thread_id; 77 /* The number of bins */ 78 block_count_t size; 79 /* A list of all packer_bins, kept sorted by free_space */ 80 struct list_head bins; 81 /* 82 * A bin to hold data_vios which were canceled out of the packer and are waiting to 83 * rendezvous with the canceling data_vio. 84 */ 85 struct packer_bin *canceled_bin; 86 87 /* The current flush generation */ 88 sequence_number_t flush_generation; 89 90 /* The administrative state of the packer */ 91 struct admin_state state; 92 93 /* Statistics are only updated on the packer thread, but are accessed from other threads */ 94 struct packer_statistics statistics; 95 }; 96 97 int vdo_get_compressed_block_fragment(enum block_mapping_state mapping_state, 98 struct compressed_block *block, 99 u16 *fragment_offset, u16 *fragment_size); 100 101 int __must_check vdo_make_packer(struct vdo *vdo, block_count_t bin_count, 102 struct packer **packer_ptr); 103 104 void vdo_free_packer(struct packer *packer); 105 106 struct packer_statistics __must_check vdo_get_packer_statistics(const struct packer *packer); 107 108 void vdo_attempt_packing(struct data_vio *data_vio); 109 110 void vdo_flush_packer(struct packer *packer); 111 112 void vdo_remove_lock_holder_from_packer(struct vdo_completion *completion); 113 114 void vdo_increment_packer_flush_generation(struct packer *packer); 115 116 void vdo_drain_packer(struct packer *packer, struct vdo_completion *completion); 117 118 void vdo_resume_packer(struct packer *packer, struct vdo_completion *parent); 119 120 void vdo_dump_packer(const struct packer *packer); 121 122 #endif /* VDO_PACKER_H */ 123