Performs the initial memory transmission (iteration zero) plus a variable number of memory iterations with the goal to eventually migrate the VM in a reasonably small downtime. This returns as soon as the precopy migration indicates it is converged (e.g., reasonably small downtime) is reached.
(
vm: &mut Vm,
socket: &mut SocketStream,
ctx: &mut MemoryMigrationContext,
is_converged: impl Fn(&MemoryMigrationContext) -> result::Result<bool, MigratableError>,
| 1201 | /// This returns as soon as the precopy migration indicates it is converged |
| 1202 | /// (e.g., reasonably small downtime) is reached. |
| 1203 | fn do_memory_iterations( |
| 1204 | vm: &mut Vm, |
| 1205 | socket: &mut SocketStream, |
| 1206 | ctx: &mut MemoryMigrationContext, |
| 1207 | is_converged: impl Fn(&MemoryMigrationContext) -> result::Result<bool, MigratableError>, |
| 1208 | mem_send: &mut SendAdditionalConnections, |
| 1209 | ) -> result::Result<MemoryRangeTable /* remaining */, MigratableError> { |
| 1210 | loop { |
| 1211 | let iteration_begin = Instant::now(); |
| 1212 | |
| 1213 | let iteration_table = if ctx.iteration == 0 { |
| 1214 | vm.memory_range_table()? |
| 1215 | } else { |
| 1216 | // TODO do this in a thread #7816 |
| 1217 | vm.dirty_log()? |
| 1218 | }; |
| 1219 | |
| 1220 | ctx.update_metrics_before_transfer(iteration_begin, &iteration_table); |
| 1221 | if is_converged(ctx)? { |
| 1222 | debug!("Precopy converged: {ctx}"); |
| 1223 | break Ok(iteration_table); |
| 1224 | } |
| 1225 | |
| 1226 | // Send the current dirty pages |
| 1227 | let transfer_begin = Instant::now(); |
| 1228 | mem_send.send_memory(iteration_table, socket)?; |
| 1229 | let transfer_duration = transfer_begin.elapsed(); |
| 1230 | ctx.update_metrics_after_transfer(transfer_begin, transfer_duration); |
| 1231 | |
| 1232 | // Log progress of the current iteration |
| 1233 | debug!("Precopy: {ctx}"); |
| 1234 | |
| 1235 | // Enables management software (e.g., libvirt) to easily track forward progress. |
| 1236 | event!( |
| 1237 | "vm", |
| 1238 | "migration-memory-iteration", |
| 1239 | "id", |
| 1240 | ctx.iteration.to_string() |
| 1241 | ); |
| 1242 | |
| 1243 | // Increment iteration last: This way we ensure that the logging |
| 1244 | // above matches the actual iteration. |
| 1245 | ctx.iteration += 1; |
| 1246 | } |
| 1247 | } |
| 1248 | |
| 1249 | /// Checks whether the precopy memory migration has converged and it is safe |
| 1250 | /// to proceed to the final (paused) memory iteration. |
nothing calls this directly
no test coverage detected