migration: Propagate errors in migration_completion_precopy()
migration_completion_precopy() doesn't propagate errors to migration core which leads to error information loss. Fix that. This prepares for a follow-up where migration_switchover_start() can fail on switchover-ack and still report a useful error. Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Peter Xu <peterx@redhat.com> Signed-off-by: Avihai Horon <avihaih@nvidia.com> Link: https://lore.kernel.org/qemu-devel/20260706085211.13905-2-avihaih@nvidia.com Signed-off-by: Cédric Le Goater <clg@redhat.com>
Avihai Horon committed
Jul 6, 2026 at 11:51 UTC
e37df09677b819746a8190c76a7d1f9942562f33
3 files changed
+26
-18
migration/migration.c
+8
-5
@@ -2820,7 +2820,7 @@ static bool migration_switchover_start(MigrationState *s, Error **errp)
2820
return true;
2821
}
2822
2823
-static int migration_completion_precopy(MigrationState *s)
2823
+static int migration_completion_precopy(MigrationState *s, Error **errp)
2824
{
2825
int ret;
2826
@@ -2829,16 +2829,17 @@ static int migration_completion_precopy(MigrationState *s)
2829
if (!migrate_mode_is_cpr()) {
2830
ret = migration_stop_vm(s, RUN_STATE_FINISH_MIGRATE);
2831
if (ret < 0) {
2832
+ error_setg_errno(errp, -ret, "Failed to stop the VM");
2833
goto out_unlock;
2834
}
2835
}
2836
2836
- if (!migration_switchover_start(s, NULL)) {
2837
+ if (!migration_switchover_start(s, errp)) {
2838
ret = -EFAULT;
2839
goto out_unlock;
2840
}
2841
2841
- ret = qemu_savevm_state_complete_precopy(s);
2842
+ ret = qemu_savevm_state_complete_precopy(s, errp);
2843
out_unlock:
2844
bql_unlock();
2845
return ret;
@@ -2875,7 +2876,7 @@ static void migration_completion(MigrationState *s)
2876
Error *local_err = NULL;
2877
2878
if (s->state == MIGRATION_STATUS_ACTIVE) {
2878
- ret = migration_completion_precopy(s);
2879
+ ret = migration_completion_precopy(s, &local_err);
2880
} else if (s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
2881
migration_completion_postcopy(s);
2882
} else {
@@ -2906,7 +2907,9 @@ static void migration_completion(MigrationState *s)
2907
return;
2908
2909
fail:
2909
- if (qemu_file_get_error_obj(s->to_dst_file, &local_err)) {
2910
+ if (local_err) {
2911
+ migrate_error_propagate(s, local_err);
2912
+ } else if (qemu_file_get_error_obj(s->to_dst_file, &local_err)) {
2913
migrate_error_propagate(s, local_err);
2914
} else if (ret) {
2915
error_setg_errno(&local_err, -ret, "Error in migration completion");
migration/savevm.c
+17
-12
@@ -1771,28 +1771,34 @@ int qemu_savevm_state_non_iterable(QEMUFile *f, Error **errp)
1771
return 0;
1772
}
1773
1774
-int qemu_savevm_state_complete_precopy(MigrationState *s)
1774
+int qemu_savevm_state_complete_precopy(MigrationState *s, Error **errp)
1775
{
1776
+ ERRP_GUARD();
1777
QEMUFile *f = s->to_dst_file;
1777
- Error *local_err = NULL;
1778
int ret;
1779
1780
ret = qemu_savevm_state_complete_precopy_iterable(f, false);
1781
if (ret) {
1782
+ qemu_file_get_error_obj(f, errp);
1783
+ error_prepend(errp, "Failed to save iterable device state: ");
1784
return ret;
1785
}
1786
1785
- /* TODO: pass error upper */
1786
- ret = qemu_savevm_state_non_iterable(f, &local_err);
1787
+ ret = qemu_savevm_state_non_iterable(f, errp);
1788
if (ret) {
1788
- migrate_error_propagate(s, error_copy(local_err));
1789
- error_report_err(local_err);
1789
return ret;
1790
}
1791
1792
qemu_savevm_state_end_precopy(s, f);
1793
1795
- return qemu_fflush(f);
1794
+ ret = qemu_fflush(f);
1795
+ if (ret) {
1796
+ qemu_file_get_error_obj(f, errp);
1797
+ error_prepend(errp, "Failed to flush QEMUFile: ");
1798
+ return ret;
1799
+ }
1800
+
1801
+ return 0;
1802
}
1803
1804
void qemu_savevm_query_pending(MigPendingData *pending, bool exact)
@@ -1874,13 +1880,12 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
1880
}
1881
1882
ret = qemu_file_get_error(f);
1877
- if (ret == 0) {
1878
- qemu_savevm_state_complete_precopy(ms);
1879
- ret = qemu_file_get_error(f);
1880
- }
1881
- if (ret != 0) {
1883
+ if (ret) {
1884
error_setg_errno(errp, -ret, "Error while writing VM state");
1885
+ goto cleanup;
1886
}
1887
+
1888
+ ret = qemu_savevm_state_complete_precopy(ms, errp);
1889
cleanup:
1890
qemu_savevm_state_cleanup();
1891
migration/savevm.h
+1
-1
@@ -44,7 +44,7 @@ void qemu_savevm_state_header(QEMUFile *f);
44
int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy);
45
void qemu_savevm_state_cleanup(void);
46
void qemu_savevm_state_complete_postcopy(QEMUFile *f);
47
-int qemu_savevm_state_complete_precopy(MigrationState *s);
47
+int qemu_savevm_state_complete_precopy(MigrationState *s, Error **errp);
48
void qemu_savevm_query_pending(MigPendingData *pending, bool exact);
49
int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy);
50
bool qemu_savevm_state_postcopy_prepare(QEMUFile *f, Error **errp);