1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright 2023 Red Hat
6 #ifndef UDS_VOLUME_INDEX_H
7 #define UDS_VOLUME_INDEX_H
9 #include <linux/limits.h>
11 #include "thread-utils.h"
14 #include "delta-index.h"
18 * The volume index is the primary top-level index for UDS. It contains records which map a record
19 * name to the chapter where a record with that name is stored. This mapping can definitively say
20 * when no record exists. However, because we only use a subset of the name for this index, it
21 * cannot definitively say that a record for the entry does exist. It can only say that if a record
22 * exists, it will be in a particular chapter. The request can then be dispatched to that chapter
23 * for further processing.
25 * If the volume_index_record does not actually match the record name, the index can store a more
26 * specific collision record to disambiguate the new entry from the existing one. Index entries are
27 * managed with volume_index_record structures.
30 #define NO_CHAPTER U64_MAX
32 struct volume_index_stats
{
33 /* Nanoseconds spent rebalancing */
34 ktime_t rebalance_time
;
35 /* Number of memory rebalances */
37 /* The number of records in the index */
39 /* The number of collision records */
41 /* The number of records removed */
43 /* The number of UDS_OVERFLOWs detected */
45 /* The number of delta lists */
47 /* Number of early flushes */
51 struct volume_sub_index_zone
{
52 u64 virtual_chapter_low
;
53 u64 virtual_chapter_high
;
55 } __aligned(L1_CACHE_BYTES
);
57 struct volume_sub_index
{
59 struct delta_index delta_index
;
60 /* The first chapter to be flushed in each zone */
63 struct volume_sub_index_zone
*zones
;
64 /* The volume nonce */
66 /* Expected size of a chapter (per zone) */
67 u64 chapter_zone_bits
;
68 /* Maximum size of the index (per zone) */
70 /* The number of bits in address mask */
72 /* Mask to get address within delta list */
74 /* The number of bits in chapter number */
76 /* The largest storable chapter number */
78 /* The number of chapters used */
80 /* The number of delta lists */
82 /* The number of zones */
83 unsigned int zone_count
;
84 /* The amount of memory allocated */
88 struct volume_index_zone
{
89 /* Protects the sampled index in this zone */
90 struct mutex hook_mutex
;
91 } __aligned(L1_CACHE_BYTES
);
94 u32 sparse_sample_rate
;
95 unsigned int zone_count
;
97 struct volume_sub_index vi_non_hook
;
98 struct volume_sub_index vi_hook
;
99 struct volume_index_zone
*zones
;
103 * The volume_index_record structure is used to facilitate processing of a record name. A client
104 * first calls uds_get_volume_index_record() to find the volume index record for a record name. The
105 * fields of the record can then be examined to determine the state of the record.
107 * If is_found is false, then the index did not find an entry for the record name. Calling
108 * uds_put_volume_index_record() will insert a new entry for that name at the proper place.
110 * If is_found is true, then we did find an entry for the record name, and the virtual_chapter and
111 * is_collision fields reflect the entry found. Subsequently, a call to
112 * uds_remove_volume_index_record() will remove the entry, a call to
113 * uds_set_volume_index_record_chapter() will update the existing entry, and a call to
114 * uds_put_volume_index_record() will insert a new collision record after the existing entry.
116 struct volume_index_record
{
119 /* Chapter where the record info is found */
121 /* This record is a collision */
123 /* This record is the requested record */
128 /* Zone that contains this name */
129 unsigned int zone_number
;
130 /* The volume index */
131 struct volume_sub_index
*sub_index
;
132 /* Mutex for accessing this delta index entry in the hook index */
134 /* The record name to which this record refers */
135 const struct uds_record_name
*name
;
136 /* The delta index entry for this record */
137 struct delta_index_entry delta_entry
;
140 int __must_check
uds_make_volume_index(const struct uds_configuration
*config
,
142 struct volume_index
**volume_index
);
144 void uds_free_volume_index(struct volume_index
*volume_index
);
146 int __must_check
uds_compute_volume_index_save_blocks(const struct uds_configuration
*config
,
150 unsigned int __must_check
uds_get_volume_index_zone(const struct volume_index
*volume_index
,
151 const struct uds_record_name
*name
);
153 bool __must_check
uds_is_volume_index_sample(const struct volume_index
*volume_index
,
154 const struct uds_record_name
*name
);
157 * This function is only used to manage sparse cache membership. Most requests should use
158 * uds_get_volume_index_record() to look up index records instead.
160 u64 __must_check
uds_lookup_volume_index_name(const struct volume_index
*volume_index
,
161 const struct uds_record_name
*name
);
163 int __must_check
uds_get_volume_index_record(struct volume_index
*volume_index
,
164 const struct uds_record_name
*name
,
165 struct volume_index_record
*record
);
167 int __must_check
uds_put_volume_index_record(struct volume_index_record
*record
,
168 u64 virtual_chapter
);
170 int __must_check
uds_remove_volume_index_record(struct volume_index_record
*record
);
172 int __must_check
uds_set_volume_index_record_chapter(struct volume_index_record
*record
,
173 u64 virtual_chapter
);
175 void uds_set_volume_index_open_chapter(struct volume_index
*volume_index
,
176 u64 virtual_chapter
);
178 void uds_set_volume_index_zone_open_chapter(struct volume_index
*volume_index
,
179 unsigned int zone_number
,
180 u64 virtual_chapter
);
182 int __must_check
uds_load_volume_index(struct volume_index
*volume_index
,
183 struct buffered_reader
**readers
,
184 unsigned int reader_count
);
186 int __must_check
uds_save_volume_index(struct volume_index
*volume_index
,
187 struct buffered_writer
**writers
,
188 unsigned int writer_count
);
190 void uds_get_volume_index_stats(const struct volume_index
*volume_index
,
191 struct volume_index_stats
*stats
);
193 #endif /* UDS_VOLUME_INDEX_H */