@samitouri / QOSamiQemu / commits / f46a11c563

system/ram-discard-manager: drop replay from source interface

Remove replay_populated and replay_discarded from RamDiscardSourceClass now that the RamDiscardManager handles replay iteration internally via is_populated. Remove the now-dead replay methods, helpers, and for_each_populated/discarded_section() from ram-block-attributes, which was the last source still carrying this code. Reviewed-by: Peter Xu <peterx@redhat.com> Acked-by: David Hildenbrand <david@kernel.org> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Link: https://lore.kernel.org/r/20260604-rdm5-v5-6-5768e6a0943d@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>

Marc-André Lureau committed Jun 4, 2026 at 17:43 UTC f46a11c563c5e0d64407f076f8589121fa86f0b0
2 files changed +10 -172
include/system/ram-discard-manager.h
+10 -42
@@ -77,8 +77,8 @@ static inline void ram_discard_listener_init(RamDiscardListener *rdl,
77 /**
78 * typedef ReplayRamDiscardState:
79 *
80 - * The callback handler for #RamDiscardSourceClass.replay_populated/
81 - * #RamDiscardSourceClass.replay_discarded to invoke on populated/discarded
80 + * The callback handler used by ram_discard_manager_replay_populated() and
81 + * ram_discard_manager_replay_discarded() to invoke on populated/discarded
82 * parts.
83 *
84 * @section: the #MemoryRegionSection of populated/discarded part
@@ -134,42 +134,6 @@ struct RamDiscardSourceClass {
134 */
135 bool (*is_populated)(const RamDiscardSource *rds,
136 const MemoryRegionSection *section);
137 -
138 - /**
139 - * @replay_populated:
140 - *
141 - * Call the #ReplayRamDiscardState callback for all populated parts within
142 - * the #MemoryRegionSection via the #RamDiscardSource.
143 - *
144 - * In case any call fails, no further calls are made.
145 - *
146 - * @rds: the #RamDiscardSource
147 - * @section: the #MemoryRegionSection
148 - * @replay_fn: the #ReplayRamDiscardState callback
149 - * @opaque: pointer to forward to the callback
150 - *
151 - * Returns 0 on success, or a negative error if any notification failed.
152 - */
153 - int (*replay_populated)(const RamDiscardSource *rds,
154 - const MemoryRegionSection *section,
155 - ReplayRamDiscardState replay_fn, void *opaque);
156 -
157 - /**
158 - * @replay_discarded:
159 - *
160 - * Call the #ReplayRamDiscardState callback for all discarded parts within
161 - * the #MemoryRegionSection via the #RamDiscardSource.
162 - *
163 - * @rds: the #RamDiscardSource
164 - * @section: the #MemoryRegionSection
165 - * @replay_fn: the #ReplayRamDiscardState callback
166 - * @opaque: pointer to forward to the callback
167 - *
168 - * Returns 0 on success, or a negative error if any notification failed.
169 - */
170 - int (*replay_discarded)(const RamDiscardSource *rds,
171 - const MemoryRegionSection *section,
172 - ReplayRamDiscardState replay_fn, void *opaque);
137 };
138
139 /**
@@ -226,8 +190,10 @@ bool ram_discard_manager_is_populated(const RamDiscardManager *rdm,
190 /**
191 * ram_discard_manager_replay_populated:
192 *
229 - * A wrapper to call the #RamDiscardSourceClass.replay_populated callback
230 - * of the #RamDiscardSource sources.
193 + * Iterate the given #MemoryRegionSection at minimum granularity, calling
194 + * #RamDiscardSourceClass.is_populated for each chunk, and invoke @replay_fn
195 + * for each contiguous populated range. In case any call fails, no further
196 + * calls are made.
197 *
198 * @rdm: the #RamDiscardManager
199 * @section: the #MemoryRegionSection
@@ -244,8 +210,10 @@ int ram_discard_manager_replay_populated(const RamDiscardManager *rdm,
210 /**
211 * ram_discard_manager_replay_discarded:
212 *
247 - * A wrapper to call the #RamDiscardSourceClass.replay_discarded callback
248 - * of the #RamDiscardSource sources.
213 + * Iterate the given #MemoryRegionSection at minimum granularity, calling
214 + * #RamDiscardSourceClass.is_populated for each chunk, and invoke @replay_fn
215 + * for each contiguous discarded range. In case any call fails, no further
216 + * calls are made.
217 *
218 * @rdm: the #RamDiscardManager
219 * @section: the #MemoryRegionSection
system/ram-block-attributes.c
-130
@@ -32,106 +32,6 @@ ram_block_attributes_get_block_size(void)
32 return qemu_real_host_page_size();
33 }
34
35 -typedef int (*ram_block_attributes_section_cb)(MemoryRegionSection *s,
36 - void *arg);
37 -
38 -static int
39 -ram_block_attributes_for_each_populated_section(const RamBlockAttributes *attr,
40 - const MemoryRegionSection *section,
41 - void *arg,
42 - ram_block_attributes_section_cb cb)
43 -{
44 - unsigned long first_bit, last_bit;
45 - uint64_t offset, size;
46 - const size_t block_size = ram_block_attributes_get_block_size();
47 - int ret = 0;
48 -
49 - first_bit = section->offset_within_region / block_size;
50 - first_bit = find_next_bit(attr->bitmap, attr->bitmap_size,
51 - first_bit);
52 -
53 - while (first_bit < attr->bitmap_size) {
54 - MemoryRegionSection tmp = *section;
55 -
56 - offset = first_bit * block_size;
57 - last_bit = find_next_zero_bit(attr->bitmap, attr->bitmap_size,
58 - first_bit + 1) - 1;
59 - size = (last_bit - first_bit + 1) * block_size;
60 -
61 - if (!memory_region_section_intersect_range(&tmp, offset, size)) {
62 - break;
63 - }
64 -
65 - ret = cb(&tmp, arg);
66 - if (ret) {
67 - error_report("%s: Failed to notify RAM discard listener: %s",
68 - __func__, strerror(-ret));
69 - break;
70 - }
71 -
72 - first_bit = find_next_bit(attr->bitmap, attr->bitmap_size,
73 - last_bit + 2);
74 - }
75 -
76 - return ret;
77 -}
78 -
79 -static int
80 -ram_block_attributes_for_each_discarded_section(const RamBlockAttributes *attr,
81 - const MemoryRegionSection *section,
82 - void *arg,
83 - ram_block_attributes_section_cb cb)
84 -{
85 - unsigned long first_bit, last_bit;
86 - uint64_t offset, size;
87 - const size_t block_size = ram_block_attributes_get_block_size();
88 - int ret = 0;
89 -
90 - first_bit = section->offset_within_region / block_size;
91 - first_bit = find_next_zero_bit(attr->bitmap, attr->bitmap_size,
92 - first_bit);
93 -
94 - while (first_bit < attr->bitmap_size) {
95 - MemoryRegionSection tmp = *section;
96 -
97 - offset = first_bit * block_size;
98 - last_bit = find_next_bit(attr->bitmap, attr->bitmap_size,
99 - first_bit + 1) - 1;
100 - size = (last_bit - first_bit + 1) * block_size;
101 -
102 - if (!memory_region_section_intersect_range(&tmp, offset, size)) {
103 - break;
104 - }
105 -
106 - ret = cb(&tmp, arg);
107 - if (ret) {
108 - error_report("%s: Failed to notify RAM discard listener: %s",
109 - __func__, strerror(-ret));
110 - break;
111 - }
112 -
113 - first_bit = find_next_zero_bit(attr->bitmap,
114 - attr->bitmap_size,
115 - last_bit + 2);
116 - }
117 -
118 - return ret;
119 -}
120 -
121 -
122 -typedef struct RamBlockAttributesReplayData {
123 - ReplayRamDiscardState fn;
124 - void *opaque;
125 -} RamBlockAttributesReplayData;
126 -
127 -static int ram_block_attributes_rds_replay_cb(MemoryRegionSection *section,
128 - void *arg)
129 -{
130 - RamBlockAttributesReplayData *data = arg;
131 -
132 - return data->fn(section, data->opaque);
133 -}
134 -
35 /* RamDiscardSource interface implementation */
36 static uint64_t
37 ram_block_attributes_rds_get_min_granularity(const RamDiscardSource *rds,
@@ -159,34 +59,6 @@ ram_block_attributes_rds_is_populated(const RamDiscardSource *rds,
59 return first_discarded_bit > last_bit;
60 }
61
162 -static int
163 -ram_block_attributes_rds_replay_populated(const RamDiscardSource *rds,
164 - const MemoryRegionSection *section,
165 - ReplayRamDiscardState replay_fn,
166 - void *opaque)
167 -{
168 - RamBlockAttributes *attr = RAM_BLOCK_ATTRIBUTES(rds);
169 - RamBlockAttributesReplayData data = { .fn = replay_fn, .opaque = opaque };
170 -
171 - g_assert(section->mr == attr->ram_block->mr);
172 - return ram_block_attributes_for_each_populated_section(attr, section, &data,
173 - ram_block_attributes_rds_replay_cb);
174 -}
175 -
176 -static int
177 -ram_block_attributes_rds_replay_discarded(const RamDiscardSource *rds,
178 - const MemoryRegionSection *section,
179 - ReplayRamDiscardState replay_fn,
180 - void *opaque)
181 -{
182 - RamBlockAttributes *attr = RAM_BLOCK_ATTRIBUTES(rds);
183 - RamBlockAttributesReplayData data = { .fn = replay_fn, .opaque = opaque };
184 -
185 - g_assert(section->mr == attr->ram_block->mr);
186 - return ram_block_attributes_for_each_discarded_section(attr, section, &data,
187 - ram_block_attributes_rds_replay_cb);
188 -}
189 -
62 static bool
63 ram_block_attributes_is_valid_range(RamBlockAttributes *attr, uint64_t offset,
64 uint64_t size)
@@ -346,6 +218,4 @@ static void ram_block_attributes_class_init(ObjectClass *klass,
218
219 rdsc->get_min_granularity = ram_block_attributes_rds_get_min_granularity;
220 rdsc->is_populated = ram_block_attributes_rds_is_populated;
349 - rdsc->replay_populated = ram_block_attributes_rds_replay_populated;
350 - rdsc->replay_discarded = ram_block_attributes_rds_replay_discarded;
221 }