mirror of https://gitee.com/openkylin/libvirt.git
qemu: process: refresh block jobs on reconnect
Block job state was widely untracked by libvirt across restarts which was allowed by a stateless block job finishing handler which discarded disk state and redetected it. This is undesirable since we'll need to track more information for individual blockjobs due to -blockdev integration requirements. In case of legacy blockjobs we can recover whether the job is present at reconnect time by querying qemu. Adding tracking whether a job is present will allow simplification of the non-shared-storage cancellation code. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
5918df1e62
commit
9ed9124d0d
|
@ -7818,6 +7818,70 @@ qemuProcessRefreshCPU(virQEMUDriverPtr driver,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessRefreshLegacyBlockjob(void *payload,
|
||||
const void *name,
|
||||
void *opaque)
|
||||
{
|
||||
const char *jobname = name;
|
||||
virDomainObjPtr vm = opaque;
|
||||
qemuMonitorBlockJobInfoPtr info = payload;
|
||||
virDomainDiskDefPtr disk;
|
||||
qemuDomainDiskPrivatePtr diskPriv;
|
||||
qemuBlockJobDataPtr job;
|
||||
|
||||
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, jobname, jobname))) {
|
||||
VIR_DEBUG("could not find disk for block job '%s'", jobname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
||||
job = diskPriv->blockjob;
|
||||
|
||||
if (disk->mirror) {
|
||||
if (info->ready == 1 ||
|
||||
(info->ready == -1 && info->end == info->cur))
|
||||
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
|
||||
}
|
||||
|
||||
job->started = true;
|
||||
job->status = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessRefreshLegacyBlockjobs(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm)
|
||||
{
|
||||
virHashTablePtr blockJobs = NULL;
|
||||
int ret = -1;
|
||||
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
blockJobs = qemuMonitorGetAllBlockJobInfo(qemuDomainGetMonitor(vm));
|
||||
if (qemuDomainObjExitMonitor(driver, vm) < 0 || !blockJobs)
|
||||
goto cleanup;
|
||||
|
||||
if (virHashForEach(blockJobs, qemuProcessRefreshLegacyBlockjob, vm) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virHashFree(blockJobs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qemuProcessRefreshBlockjobs(virQEMUDriverPtr driver,
|
||||
virDomainObjPtr vm)
|
||||
{
|
||||
return qemuProcessRefreshLegacyBlockjobs(driver, vm);
|
||||
}
|
||||
|
||||
|
||||
struct qemuProcessReconnectData {
|
||||
virQEMUDriverPtr driver;
|
||||
virDomainObjPtr obj;
|
||||
|
@ -8021,6 +8085,9 @@ qemuProcessReconnect(void *opaque)
|
|||
qemuBlockNodeNamesDetect(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
||||
goto error;
|
||||
|
||||
if (qemuProcessRefreshBlockjobs(driver, obj) < 0)
|
||||
goto error;
|
||||
|
||||
if (qemuRefreshVirtioChannelState(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
|
||||
goto error;
|
||||
|
||||
|
|
Loading…
Reference in New Issue