From 94003024770478f1b894dde792d7b00946f4dade Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Fri, 4 Oct 2019 16:28:47 +0200 Subject: [PATCH] qemu: blockjob: Implement concluded blockjob handler for backup blockjobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the individual sub-blockjobs of a backup libvirt job finish we must detect it and notify the parent job, so that it can be properly terminated. Since we update job information to determine success of a blockjob we can directly report back also statistics of the blockjob. Signed-off-by: Peter Krempa Reviewed-by: Eric Blake Reviewed-by: Ján Tomko --- src/qemu/qemu_blockjob.c | 74 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index b17577e987..81aa46c2fb 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -27,6 +27,7 @@ #include "qemu_block.h" #include "qemu_domain.h" #include "qemu_alias.h" +#include "qemu_backup.h" #include "conf/domain_conf.h" #include "conf/domain_event.h" @@ -1277,11 +1278,71 @@ qemuBlockJobProcessEventConcludedCreate(virQEMUDriverPtr driver, } +static void +qemuBlockJobProcessEventConcludedBackup(virQEMUDriverPtr driver, + virDomainObjPtr vm, + qemuBlockJobDataPtr job, + qemuDomainAsyncJob asyncJob, + qemuBlockjobState newstate, + unsigned long long progressCurrent, + unsigned long long progressTotal) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + uid_t uid; + gid_t gid; + g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL; + g_autoptr(virJSONValue) actions = NULL; + + qemuBackupNotifyBlockjobEnd(vm, job->disk, newstate, progressCurrent, progressTotal); + + if (job->data.backup.store && + !(backend = qemuBlockStorageSourceDetachPrepare(job->data.backup.store, NULL))) + return; + + if (job->data.backup.bitmap) { + if (!(actions = virJSONValueNewArray())) + return; + + if (qemuMonitorTransactionBitmapRemove(actions, + job->disk->src->nodeformat, + job->data.backup.bitmap) < 0) + return; + } + + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + return; + + if (backend) + qemuBlockStorageSourceAttachRollback(qemuDomainGetMonitor(vm), backend); + + if (actions) + qemuMonitorTransaction(qemuDomainGetMonitor(vm), &actions); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + return; + + if (job->data.backup.store) { + qemuDomainStorageSourceAccessRevoke(driver, vm, job->data.backup.store); + + if (job->data.backup.deleteStore && + job->data.backup.store->type == VIR_STORAGE_TYPE_FILE) { + qemuDomainGetImageIds(cfg, vm, job->data.backup.store, NULL, &uid, &gid); + + if (virFileRemove(job->data.backup.store->path, uid, gid) < 0) + VIR_WARN("failed to remove scratch file '%s'", + job->data.backup.store->path); + } + } +} + + static void qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job, virQEMUDriverPtr driver, virDomainObjPtr vm, - qemuDomainAsyncJob asyncJob) + qemuDomainAsyncJob asyncJob, + unsigned long long progressCurrent, + unsigned long long progressTotal) { bool success = job->newstate == QEMU_BLOCKJOB_STATE_COMPLETED; @@ -1315,6 +1376,9 @@ qemuBlockJobEventProcessConcludedTransition(qemuBlockJobDataPtr job, break; case QEMU_BLOCKJOB_TYPE_BACKUP: + qemuBlockJobProcessEventConcludedBackup(driver, vm, job, asyncJob, + job->newstate, progressCurrent, + progressTotal); break; case QEMU_BLOCKJOB_TYPE_BROKEN: @@ -1341,6 +1405,8 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job, size_t njobinfo = 0; size_t i; bool refreshed = false; + unsigned long long progressCurrent = 0; + unsigned long long progressTotal = 0; if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) goto cleanup; @@ -1353,6 +1419,9 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job, if (STRNEQ_NULLABLE(job->name, jobinfo[i]->id)) continue; + progressCurrent = jobinfo[i]->progressCurrent; + progressTotal = jobinfo[i]->progressTotal; + job->errmsg = g_strdup(jobinfo[i]->error); if (job->errmsg) @@ -1385,7 +1454,8 @@ qemuBlockJobEventProcessConcluded(qemuBlockJobDataPtr job, VIR_DEBUG("handling job '%s' state '%d' newstate '%d'", job->name, job->state, job->newstate); - qemuBlockJobEventProcessConcludedTransition(job, driver, vm, asyncJob); + qemuBlockJobEventProcessConcludedTransition(job, driver, vm, asyncJob, + progressCurrent, progressTotal); /* unplug the backing chains in case the job inherited them */ if (!job->disk) {