From b37fdfb9d4ead0a01377837e02ecedee48337c97 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Thu, 16 Apr 2020 11:23:07 +0200 Subject: [PATCH] backup: Store error message for failed backups If a backup job fails midway it's hard to figure out what happened as it's running asynchronous. Use the VIR_DOMAIN_JOB_ERRMSG job statistics field to pass through the error from the first failed backup-blockjob so that both the consumer of the virDomainGetJobStats and the corresponding event can see the error. event 'job-completed' for domain backup-test: operation: 9 time_elapsed: 46 disk_total: 104857600 disk_processed: 10158080 disk_remaining: 94699520 success: 0 errmsg: No space left on device virsh domjobinfo backup-test --completed --anystats Job type: Failed Operation: Backup Time elapsed: 46 ms File processed: 9.688 MiB File remaining: 90.312 MiB File total: 100.000 MiB Error message: No space left on device https://bugzilla.redhat.com/show_bug.cgi?id=1812827 Signed-off-by: Peter Krempa Reviewed-by: Eric Blake --- src/conf/backup_conf.c | 1 + src/conf/backup_conf.h | 2 ++ src/qemu/qemu_backup.c | 10 ++++++++-- src/qemu/qemu_backup.h | 1 + src/qemu/qemu_blockjob.c | 2 +- src/qemu/qemu_domain.c | 4 ++++ 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/conf/backup_conf.c b/src/conf/backup_conf.c index 64c8f6cc09..c5677cdb05 100644 --- a/src/conf/backup_conf.c +++ b/src/conf/backup_conf.c @@ -65,6 +65,7 @@ virDomainBackupDefFree(virDomainBackupDefPtr def) return; g_free(def->incremental); + g_free(def->errmsg); virStorageNetHostDefFree(1, def->server); for (i = 0; i < def->ndisks; i++) { diff --git a/src/conf/backup_conf.h b/src/conf/backup_conf.h index 672fd52ee7..b5685317c5 100644 --- a/src/conf/backup_conf.h +++ b/src/conf/backup_conf.h @@ -79,6 +79,8 @@ struct _virDomainBackupDef { unsigned long long push_total; unsigned long long pull_tmp_used; unsigned long long pull_tmp_total; + + char *errmsg; /* error message of failed sub-blockjob */ }; typedef enum { diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index 03d34c9378..80fc5d77f8 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -650,6 +650,7 @@ qemuBackupJobTerminate(virDomainObjPtr vm, priv->job.completed->stats.backup.tmp_total = priv->backup->pull_tmp_total; priv->job.completed->status = jobstatus; + priv->job.completed->errmsg = g_strdup(priv->backup->errmsg); qemuDomainEventEmitJobCompleted(priv->driver, vm); @@ -951,6 +952,7 @@ void qemuBackupNotifyBlockjobEnd(virDomainObjPtr vm, virDomainDiskDefPtr disk, qemuBlockjobState state, + const char *errmsg, unsigned long long cur, unsigned long long end, int asyncJob) @@ -964,8 +966,8 @@ qemuBackupNotifyBlockjobEnd(virDomainObjPtr vm, virDomainBackupDefPtr backup = priv->backup; size_t i; - VIR_DEBUG("vm: '%s', disk:'%s', state:'%d'", - vm->def->name, disk->dst, state); + VIR_DEBUG("vm: '%s', disk:'%s', state:'%d' errmsg:'%s'", + vm->def->name, disk->dst, state, NULLSTR(errmsg)); if (!backup) return; @@ -985,6 +987,10 @@ qemuBackupNotifyBlockjobEnd(virDomainObjPtr vm, backup->push_total += end; } + /* record first error message */ + if (!backup->errmsg) + backup->errmsg = g_strdup(errmsg); + for (i = 0; i < backup->ndisks; i++) { virDomainBackupDiskDefPtr backupdisk = backup->disks + i; diff --git a/src/qemu/qemu_backup.h b/src/qemu/qemu_backup.h index 3321ba0b6f..b19c3bf1c9 100644 --- a/src/qemu/qemu_backup.h +++ b/src/qemu/qemu_backup.h @@ -38,6 +38,7 @@ void qemuBackupNotifyBlockjobEnd(virDomainObjPtr vm, virDomainDiskDefPtr disk, qemuBlockjobState state, + const char *errmsg, unsigned long long cur, unsigned long long end, int asyncJob); diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index 2032c0c1c5..b9eecd3f98 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -1435,7 +1435,7 @@ qemuBlockJobProcessEventConcludedBackup(virQEMUDriverPtr driver, g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL; g_autoptr(virJSONValue) actions = NULL; - qemuBackupNotifyBlockjobEnd(vm, job->disk, newstate, + qemuBackupNotifyBlockjobEnd(vm, job->disk, newstate, job->errmsg, progressCurrent, progressTotal, asyncJob); if (job->data.backup.store && diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 0378a833b9..d63ec2313b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -836,6 +836,10 @@ qemuDomainBackupJobInfoToParams(qemuDomainJobInfoPtr jobInfo, VIR_DOMAIN_JOB_SUCCESS) < 0) return -1; + if (jobInfo->errmsg && + virTypedParamListAddString(par, jobInfo->errmsg, VIR_DOMAIN_JOB_ERRMSG) < 0) + return -1; + *nparams = virTypedParamListStealParams(par, params); *type = qemuDomainJobStatusToType(jobInfo->status); return 0; -- GitLab