mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 09:53:10 +00:00
qemu: blockjob: Add functions for block job state control
Rather than directly modifying fields in the qemuBlockJobDataPtr structure add a bunch of fields which allow to do the transitions. This will help later when adding more complexity to the job handling. APIs introduced in this patch are: qemuBlockJobDiskNew - prepare for starting a new blockjob on a disk qemuBlockJobDiskGetJob - get the block job data structure for a disk For individual job state manipulation the following APIs are added: qemuBlockJobStarted - Sets the job as started with qemu. Until that the job can be cancelled without asking qemu. qemuBlockJobStartupFinalize - finalize job startup. If the job was started in qemu already, just releases reference to the job object. Otherwise clears everything as if the job was never started. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
b44f1cd7d7
commit
e0c4d4fcf0
@ -76,6 +76,87 @@ qemuBlockJobDataNew(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
qemuBlockJobDataReset(qemuBlockJobDataPtr job)
|
||||||
|
{
|
||||||
|
job->started = false;
|
||||||
|
job->type = -1;
|
||||||
|
job->newstate = -1;
|
||||||
|
VIR_FREE(job->errmsg);
|
||||||
|
job->synchronous = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBlockJobDiskNew:
|
||||||
|
* @disk: disk definition
|
||||||
|
*
|
||||||
|
* Start/associate a new blockjob with @disk.
|
||||||
|
*
|
||||||
|
* Returns 0 on success and -1 on failure.
|
||||||
|
*/
|
||||||
|
qemuBlockJobDataPtr
|
||||||
|
qemuBlockJobDiskNew(virDomainDiskDefPtr disk)
|
||||||
|
{
|
||||||
|
qemuBlockJobDataPtr job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
|
||||||
|
|
||||||
|
qemuBlockJobDataReset(job);
|
||||||
|
return virObjectRef(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBlockJobDiskGetJob:
|
||||||
|
* @disk: disk definition
|
||||||
|
*
|
||||||
|
* Get a reference to the block job data object associated with @disk.
|
||||||
|
*/
|
||||||
|
qemuBlockJobDataPtr
|
||||||
|
qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk)
|
||||||
|
{
|
||||||
|
qemuBlockJobDataPtr job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
|
||||||
|
|
||||||
|
if (!job)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return virObjectRef(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBlockJobStarted:
|
||||||
|
* @job: job data
|
||||||
|
*
|
||||||
|
* Mark @job as started in qemu.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
qemuBlockJobStarted(qemuBlockJobDataPtr job)
|
||||||
|
{
|
||||||
|
job->started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemuBlockJobStartupFinalize:
|
||||||
|
* @job: job being started
|
||||||
|
*
|
||||||
|
* Cancels and clears the job private data if the job was not started with
|
||||||
|
* qemu (see qemuBlockJobStarted) or just clears up the local reference
|
||||||
|
* to @job if it was started.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job)
|
||||||
|
{
|
||||||
|
if (!job)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!job->started)
|
||||||
|
qemuBlockJobDataReset(job);
|
||||||
|
|
||||||
|
virObjectUnref(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemuBlockJobEmitEvents:
|
* qemuBlockJobEmitEvents:
|
||||||
*
|
*
|
||||||
|
@ -42,6 +42,21 @@ struct _qemuBlockJobData {
|
|||||||
|
|
||||||
qemuBlockJobDataPtr qemuBlockJobDataNew(void);
|
qemuBlockJobDataPtr qemuBlockJobDataNew(void);
|
||||||
|
|
||||||
|
qemuBlockJobDataPtr
|
||||||
|
qemuBlockJobDiskNew(virDomainDiskDefPtr disk)
|
||||||
|
ATTRIBUTE_NONNULL(1);
|
||||||
|
|
||||||
|
qemuBlockJobDataPtr
|
||||||
|
qemuBlockJobDiskGetJob(virDomainDiskDefPtr disk)
|
||||||
|
ATTRIBUTE_NONNULL(1);
|
||||||
|
|
||||||
|
void
|
||||||
|
qemuBlockJobStarted(qemuBlockJobDataPtr job)
|
||||||
|
ATTRIBUTE_NONNULL(1);
|
||||||
|
|
||||||
|
void
|
||||||
|
qemuBlockJobStartupFinalize(qemuBlockJobDataPtr job);
|
||||||
|
|
||||||
int qemuBlockJobUpdateDisk(virDomainObjPtr vm,
|
int qemuBlockJobUpdateDisk(virDomainObjPtr vm,
|
||||||
int asyncJob,
|
int asyncJob,
|
||||||
virDomainDiskDefPtr disk,
|
virDomainDiskDefPtr disk,
|
||||||
@ -52,4 +67,8 @@ void qemuBlockJobSyncEndDisk(virDomainObjPtr vm,
|
|||||||
int asyncJob,
|
int asyncJob,
|
||||||
virDomainDiskDefPtr disk);
|
virDomainDiskDefPtr disk);
|
||||||
|
|
||||||
|
qemuBlockJobDataPtr
|
||||||
|
qemuBlockJobGetByDisk(virDomainDiskDefPtr disk)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
|
||||||
|
|
||||||
#endif /* LIBVIRT_QEMU_BLOCKJOB_H */
|
#endif /* LIBVIRT_QEMU_BLOCKJOB_H */
|
||||||
|
@ -4717,7 +4717,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|||||||
int status)
|
int status)
|
||||||
{
|
{
|
||||||
virDomainDiskDefPtr disk;
|
virDomainDiskDefPtr disk;
|
||||||
qemuBlockJobDataPtr job;
|
qemuBlockJobDataPtr job = NULL;
|
||||||
|
|
||||||
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
||||||
return;
|
return;
|
||||||
@ -4732,7 +4732,11 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
|
if (!(job = qemuBlockJobDiskGetJob(disk))) {
|
||||||
|
if (!(job = qemuBlockJobDiskNew(disk)))
|
||||||
|
goto endjob;
|
||||||
|
qemuBlockJobStarted(job);
|
||||||
|
}
|
||||||
|
|
||||||
job->type = type;
|
job->type = type;
|
||||||
job->newstate = status;
|
job->newstate = status;
|
||||||
@ -4740,6 +4744,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|||||||
qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
|
qemuBlockJobUpdateDisk(vm, QEMU_ASYNC_JOB_NONE, disk, NULL);
|
||||||
|
|
||||||
endjob:
|
endjob:
|
||||||
|
qemuBlockJobStartupFinalize(job);
|
||||||
qemuDomainObjEndJob(driver, vm);
|
qemuDomainObjEndJob(driver, vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17245,6 +17250,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
|
|||||||
char *basePath = NULL;
|
char *basePath = NULL;
|
||||||
char *backingPath = NULL;
|
char *backingPath = NULL;
|
||||||
unsigned long long speed = bandwidth;
|
unsigned long long speed = bandwidth;
|
||||||
|
qemuBlockJobDataPtr job = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
|
if (flags & VIR_DOMAIN_BLOCK_REBASE_RELATIVE && !base) {
|
||||||
@ -17311,6 +17317,9 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
|
|||||||
speed <<= 20;
|
speed <<= 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(job = qemuBlockJobDiskNew(disk)))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
if (baseSource)
|
if (baseSource)
|
||||||
basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
|
basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
|
||||||
@ -17324,7 +17333,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true;
|
qemuBlockJobStarted(job);
|
||||||
|
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
|
||||||
VIR_WARN("Unable to save status on vm %s after state change",
|
VIR_WARN("Unable to save status on vm %s after state change",
|
||||||
@ -17334,6 +17343,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
|
|||||||
qemuDomainObjEndJob(driver, vm);
|
qemuDomainObjEndJob(driver, vm);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
qemuBlockJobStartupFinalize(job);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
VIR_FREE(basePath);
|
VIR_FREE(basePath);
|
||||||
VIR_FREE(backingPath);
|
VIR_FREE(backingPath);
|
||||||
@ -17711,6 +17721,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
|
|||||||
const char *format = NULL;
|
const char *format = NULL;
|
||||||
virErrorPtr monitor_error = NULL;
|
virErrorPtr monitor_error = NULL;
|
||||||
bool reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT);
|
bool reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT);
|
||||||
|
qemuBlockJobDataPtr job = NULL;
|
||||||
|
|
||||||
/* Preliminaries: find the disk we are editing, sanity checks */
|
/* Preliminaries: find the disk we are editing, sanity checks */
|
||||||
virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
|
virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
|
||||||
@ -17834,6 +17845,9 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(job = qemuBlockJobDiskNew(disk)))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
/* Actually start the mirroring */
|
/* Actually start the mirroring */
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
/* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified
|
/* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified
|
||||||
@ -17850,12 +17864,12 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update vm in place to match changes. */
|
/* Update vm in place to match changes. */
|
||||||
|
qemuBlockJobStarted(job);
|
||||||
need_unlink = false;
|
need_unlink = false;
|
||||||
virStorageFileDeinit(mirror);
|
virStorageFileDeinit(mirror);
|
||||||
disk->mirror = mirror;
|
disk->mirror = mirror;
|
||||||
mirror = NULL;
|
mirror = NULL;
|
||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
|
||||||
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true;
|
|
||||||
|
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
|
||||||
VIR_WARN("Unable to save status on vm %s after state change",
|
VIR_WARN("Unable to save status on vm %s after state change",
|
||||||
@ -17870,6 +17884,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
|
|||||||
virSetError(monitor_error);
|
virSetError(monitor_error);
|
||||||
virFreeError(monitor_error);
|
virFreeError(monitor_error);
|
||||||
}
|
}
|
||||||
|
qemuBlockJobStartupFinalize(job);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(device);
|
VIR_FREE(device);
|
||||||
@ -18080,6 +18095,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
char *backingPath = NULL;
|
char *backingPath = NULL;
|
||||||
virStorageSourcePtr mirror = NULL;
|
virStorageSourcePtr mirror = NULL;
|
||||||
unsigned long long speed = bandwidth;
|
unsigned long long speed = bandwidth;
|
||||||
|
qemuBlockJobDataPtr job = NULL;
|
||||||
|
|
||||||
/* XXX Add support for COMMIT_DELETE */
|
/* XXX Add support for COMMIT_DELETE */
|
||||||
virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
|
virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
|
||||||
@ -18240,6 +18256,10 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
disk->mirror = mirror;
|
disk->mirror = mirror;
|
||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(job = qemuBlockJobDiskNew(disk)))
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
|
basePath = qemuMonitorDiskNameLookup(priv->mon, device, disk->src,
|
||||||
baseSource);
|
baseSource);
|
||||||
@ -18255,7 +18275,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob->started = true;
|
qemuBlockJobStarted(job);
|
||||||
mirror = NULL;
|
mirror = NULL;
|
||||||
} else {
|
} else {
|
||||||
disk->mirror = NULL;
|
disk->mirror = NULL;
|
||||||
@ -18280,6 +18300,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
virStorageSourceFree(mirror);
|
virStorageSourceFree(mirror);
|
||||||
|
qemuBlockJobStartupFinalize(job);
|
||||||
qemuDomainObjEndJob(driver, vm);
|
qemuDomainObjEndJob(driver, vm);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -902,6 +902,7 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver,
|
|||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
||||||
|
qemuBlockJobDataPtr job = NULL;
|
||||||
char *diskAlias = NULL;
|
char *diskAlias = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@ -909,6 +910,9 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver,
|
|||||||
if (!(diskAlias = qemuAliasDiskDriveFromDisk(disk)))
|
if (!(diskAlias = qemuAliasDiskDriveFromDisk(disk)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(job = qemuBlockJobDiskNew(disk)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
qemuBlockJobSyncBeginDisk(disk);
|
qemuBlockJobSyncBeginDisk(disk);
|
||||||
|
|
||||||
if (flags & VIR_MIGRATE_TLS) {
|
if (flags & VIR_MIGRATE_TLS) {
|
||||||
@ -931,11 +935,12 @@ qemuMigrationSrcNBDStorageCopyOne(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
diskPriv->migrating = true;
|
diskPriv->migrating = true;
|
||||||
diskPriv->blockjob->started = true;
|
qemuBlockJobStarted(job);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
qemuBlockJobStartupFinalize(job);
|
||||||
VIR_FREE(diskAlias);
|
VIR_FREE(diskAlias);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -927,7 +927,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
virQEMUDriverPtr driver = opaque;
|
virQEMUDriverPtr driver = opaque;
|
||||||
struct qemuProcessEvent *processEvent = NULL;
|
struct qemuProcessEvent *processEvent = NULL;
|
||||||
virDomainDiskDefPtr disk;
|
virDomainDiskDefPtr disk;
|
||||||
qemuBlockJobDataPtr job;
|
qemuBlockJobDataPtr job = NULL;
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
|
|
||||||
virObjectLock(vm);
|
virObjectLock(vm);
|
||||||
@ -938,9 +938,9 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL)))
|
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, diskAlias, NULL)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
job = QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob;
|
job = qemuBlockJobDiskGetJob(disk);
|
||||||
|
|
||||||
if (job->synchronous) {
|
if (job && job->synchronous) {
|
||||||
/* We have a SYNC API waiting for this event, dispatch it back */
|
/* We have a SYNC API waiting for this event, dispatch it back */
|
||||||
job->type = type;
|
job->type = type;
|
||||||
job->newstate = status;
|
job->newstate = status;
|
||||||
@ -969,6 +969,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
qemuBlockJobStartupFinalize(job);
|
||||||
qemuProcessEventFree(processEvent);
|
qemuProcessEventFree(processEvent);
|
||||||
virObjectUnlock(vm);
|
virObjectUnlock(vm);
|
||||||
return 0;
|
return 0;
|
||||||
@ -7827,7 +7828,6 @@ qemuProcessRefreshLegacyBlockjob(void *payload,
|
|||||||
virDomainObjPtr vm = opaque;
|
virDomainObjPtr vm = opaque;
|
||||||
qemuMonitorBlockJobInfoPtr info = payload;
|
qemuMonitorBlockJobInfoPtr info = payload;
|
||||||
virDomainDiskDefPtr disk;
|
virDomainDiskDefPtr disk;
|
||||||
qemuDomainDiskPrivatePtr diskPriv;
|
|
||||||
qemuBlockJobDataPtr job;
|
qemuBlockJobDataPtr job;
|
||||||
|
|
||||||
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, jobname, jobname))) {
|
if (!(disk = qemuProcessFindDomainDiskByAliasOrQOM(vm, jobname, jobname))) {
|
||||||
@ -7835,8 +7835,10 @@ qemuProcessRefreshLegacyBlockjob(void *payload,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
|
if (!(job = qemuBlockJobDiskNew(disk)))
|
||||||
job = diskPriv->blockjob;
|
return -1;
|
||||||
|
|
||||||
|
qemuBlockJobStarted(job);
|
||||||
|
|
||||||
if (disk->mirror) {
|
if (disk->mirror) {
|
||||||
if (info->ready == 1 ||
|
if (info->ready == 1 ||
|
||||||
@ -7844,8 +7846,7 @@ qemuProcessRefreshLegacyBlockjob(void *payload,
|
|||||||
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
|
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
job->started = true;
|
qemuBlockJobStartupFinalize(job);
|
||||||
job->newstate = -1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user