123 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright 2023 Red Hat4 */5 6#ifndef VDO_PACKER_H7#define VDO_PACKER_H8 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 18enum {19 DEFAULT_PACKER_BINS = 16,20};21 22/* The header of a compressed block. */23struct 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 31enum {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 a36 * 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. */42struct 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 compressed49 * block. The bins are kept in a ring sorted by the amount of unused space so the first bin with50 * enough space to hold a newly-compressed data_vio can easily be found. When the bin fills up or51 * 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 the53 * data_vio's compressed_block (overlaid on the data_vio's scratch_block). So the agent's fragment54 * is already in place. The fragments for the other uncanceled data_vios in the bin are packed into55 * the agent's compressed block. The agent then writes out the compressed block. If the write is56 * successful, the agent shares its pbn lock which each of the other data_vios in its compressed57 * 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 removed60 * from their bin by the packer. These data_vios need to wait for the canceller to rendezvous with61 * them and so they sit in this special bin.62 */63struct 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 74struct 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 to83 * 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 97int vdo_get_compressed_block_fragment(enum block_mapping_state mapping_state,98 struct compressed_block *block,99 u16 *fragment_offset, u16 *fragment_size);100 101int __must_check vdo_make_packer(struct vdo *vdo, block_count_t bin_count,102 struct packer **packer_ptr);103 104void vdo_free_packer(struct packer *packer);105 106struct packer_statistics __must_check vdo_get_packer_statistics(const struct packer *packer);107 108void vdo_attempt_packing(struct data_vio *data_vio);109 110void vdo_flush_packer(struct packer *packer);111 112void vdo_remove_lock_holder_from_packer(struct vdo_completion *completion);113 114void vdo_increment_packer_flush_generation(struct packer *packer);115 116void vdo_drain_packer(struct packer *packer, struct vdo_completion *completion);117 118void vdo_resume_packer(struct packer *packer, struct vdo_completion *parent);119 120void vdo_dump_packer(const struct packer *packer);121 122#endif /* VDO_PACKER_H */123