1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright 2023 Red Hat
9 #include <linux/list.h>
11 #include "admin-state.h"
12 #include "constants.h"
13 #include "encodings.h"
14 #include "statistics.h"
16 #include "wait-queue.h"
19 DEFAULT_PACKER_BINS
= 16,
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
;
27 /* List of unsigned 16-bit compressed block sizes, little-endian */
28 __le16 sizes
[VDO_MAX_COMPRESSION_SLOTS
];
32 VDO_COMPRESSED_BLOCK_DATA_SIZE
= VDO_BLOCK_SIZE
- sizeof(struct compressed_block_header
),
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.
38 VDO_MAX_COMPRESSED_FRAGMENT_SIZE
= VDO_COMPRESSED_BLOCK_DATA_SIZE
- 1,
41 /* * The compressed block overlay. */
42 struct compressed_block
{
43 struct compressed_block_header header
;
44 char data
[VDO_COMPRESSED_BLOCK_DATA_SIZE
];
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.
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.
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 */
70 /* The current partial batch of data_vios, waiting for more */
71 struct data_vio
*incoming
[];
75 /* The ID of the packer's callback thread */
76 thread_id_t thread_id
;
77 /* The number of bins */
79 /* A list of all packer_bins, kept sorted by free_space */
80 struct list_head bins
;
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.
85 struct packer_bin
*canceled_bin
;
87 /* The current flush generation */
88 sequence_number_t flush_generation
;
90 /* The administrative state of the packer */
91 struct admin_state state
;
93 /* Statistics are only updated on the packer thread, but are accessed from other threads */
94 struct packer_statistics statistics
;
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
);
101 int __must_check
vdo_make_packer(struct vdo
*vdo
, block_count_t bin_count
,
102 struct packer
**packer_ptr
);
104 void vdo_free_packer(struct packer
*packer
);
106 struct packer_statistics __must_check
vdo_get_packer_statistics(const struct packer
*packer
);
108 void vdo_attempt_packing(struct data_vio
*data_vio
);
110 void vdo_flush_packer(struct packer
*packer
);
112 void vdo_remove_lock_holder_from_packer(struct vdo_completion
*completion
);
114 void vdo_increment_packer_flush_generation(struct packer
*packer
);
116 void vdo_drain_packer(struct packer
*packer
, struct vdo_completion
*completion
);
118 void vdo_resume_packer(struct packer
*packer
, struct vdo_completion
*parent
);
120 void vdo_dump_packer(const struct packer
*packer
);
122 #endif /* VDO_PACKER_H */