]> Git Repo - linux.git/blob - drivers/md/dm-vdo/packer.h
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux.git] / drivers / md / dm-vdo / packer.h
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 */
This page took 0.042549 seconds and 4 git commands to generate.