Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
Notes:
Version 2:
- new patch
src/conf/domain_conf.c | 6 -----
src/conf/domain_conf.h | 10 --------
src/libvirt_private.syms | 1 -
src/qemu/qemu_blockjob.c | 48 +++++++++++++++++++++----------------
src/qemu/qemu_domain.c | 61 +++++++++++++++++++++++++++++++++++++++++++----
src/qemu/qemu_domain.h | 21 ++++++++++++++++
src/qemu/qemu_driver.c | 11 +++++----
src/qemu/qemu_migration.c | 6 +++--
src/qemu/qemu_process.c | 17 +++++++------
9 files changed, 125 insertions(+), 56 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3204140..bf0099d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1290,11 +1290,6 @@ virDomainDiskDefNew(virDomainXMLOptionPtr xmlopt)
!(ret->privateData = xmlopt->privateData.diskNew()))
goto error;
- if (virCondInit(&ret->blockJobSyncCond) < 0) {
- virReportSystemError(errno, "%s", _("Failed to initialize
condition"));
- goto error;
- }
-
return ret;
error:
@@ -1319,7 +1314,6 @@ virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->domain_name);
virDomainDeviceInfoClear(&def->info);
virObjectUnref(def->privateData);
- virCondDestroy(&def->blockJobSyncCond);
VIR_FREE(def);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b5e7617..8312c20 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -691,20 +691,10 @@ struct _virDomainDiskDef {
int tray_status; /* enum virDomainDiskTray */
int removable; /* enum virTristateSwitch */
- /* ideally we want a smarter way to interlock block jobs on single qemu disk
- * in the future, but for now we just disallow any concurrent job on a
- * single disk */
- bool blockjob;
virStorageSourcePtr mirror;
int mirrorState; /* enum virDomainDiskMirrorState */
int mirrorJob; /* virDomainBlockJobType */
- /* for some synchronous block jobs, we need to notify the owner */
- virCond blockJobSyncCond;
- int blockJobType; /* type of the block job from the event */
- int blockJobStatus; /* status of the finished block job */
- bool blockJobSync; /* the block job needs synchronized termination */
-
struct {
unsigned int cylinders;
unsigned int heads;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 67a7e21..2586572 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -308,7 +308,6 @@ virDomainGraphicsTypeFromString;
virDomainGraphicsTypeToString;
virDomainGraphicsVNCSharePolicyTypeFromString;
virDomainGraphicsVNCSharePolicyTypeToString;
-virDomainHasBlockjob;
virDomainHasNet;
virDomainHostdevCapsTypeToString;
virDomainHostdevDefAlloc;
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 729928a..b9572d0 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -65,6 +65,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainDiskDefPtr persistDisk = NULL;
bool save = false;
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
/* Have to generate two variants of the event for old vs. new
* client callbacks */
@@ -127,7 +128,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
true, true));
- disk->blockjob = false;
+ diskPriv->blockjob = false;
break;
case VIR_DOMAIN_BLOCK_JOB_READY:
@@ -143,7 +144,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
VIR_DOMAIN_DISK_MIRROR_STATE_ABORT : VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
save = true;
- disk->blockjob = false;
+ diskPriv->blockjob = false;
break;
case VIR_DOMAIN_BLOCK_JOB_LAST:
@@ -185,11 +186,13 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
void
qemuBlockJobSyncBegin(virDomainDiskDefPtr disk)
{
- if (disk->blockJobSync)
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+
+ if (diskPriv->blockJobSync)
VIR_WARN("Disk %s already has synchronous block job",
disk->dst);
- disk->blockJobSync = true;
+ diskPriv->blockJobSync = true;
}
@@ -211,15 +214,17 @@ qemuBlockJobSyncEnd(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk,
virConnectDomainEventBlockJobStatus *ret_status)
{
- if (disk->blockJobSync && disk->blockJobStatus != -1) {
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+
+ if (diskPriv->blockJobSync && diskPriv->blockJobStatus != -1) {
if (ret_status)
- *ret_status = disk->blockJobStatus;
+ *ret_status = diskPriv->blockJobStatus;
qemuBlockJobEventProcess(driver, vm, disk,
- disk->blockJobType,
- disk->blockJobStatus);
- disk->blockJobStatus = -1;
+ diskPriv->blockJobType,
+ diskPriv->blockJobStatus);
+ diskPriv->blockJobStatus = -1;
}
- disk->blockJobSync = false;
+ diskPriv->blockJobSync = false;
}
@@ -248,24 +253,26 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
unsigned long long timeout,
virConnectDomainEventBlockJobStatus *ret_status)
{
- if (!disk->blockJobSync) {
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+
+ if (!diskPriv->blockJobSync) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No current synchronous block job"));
return -1;
}
- while (disk->blockJobSync && disk->blockJobStatus == -1) {
+ while (diskPriv->blockJobSync && diskPriv->blockJobStatus == -1) {
int r;
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
- disk->blockJobSync = false;
+ diskPriv->blockJobSync = false;
return -1;
}
if (timeout == (unsigned long long)-1) {
- r = virCondWait(&disk->blockJobSyncCond, &vm->parent.lock);
+ r = virCondWait(&diskPriv->blockJobSyncCond,
&vm->parent.lock);
} else if (timeout) {
unsigned long long now;
if (virTimeMillisNow(&now) < 0) {
@@ -273,7 +280,8 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
_("Unable to get current time"));
return -1;
}
- r = virCondWaitUntil(&disk->blockJobSyncCond,
&vm->parent.lock,
+ r = virCondWaitUntil(&diskPriv->blockJobSyncCond,
+ &vm->parent.lock,
now + timeout);
if (r < 0 && errno == ETIMEDOUT)
return 0;
@@ -283,7 +291,7 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
}
if (r < 0) {
- disk->blockJobSync = false;
+ diskPriv->blockJobSync = false;
virReportSystemError(errno, "%s",
_("Unable to wait on block job sync "
"condition"));
@@ -292,11 +300,11 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
}
if (ret_status)
- *ret_status = disk->blockJobStatus;
+ *ret_status = diskPriv->blockJobStatus;
qemuBlockJobEventProcess(driver, vm, disk,
- disk->blockJobType,
- disk->blockJobStatus);
- disk->blockJobStatus = -1;
+ diskPriv->blockJobType,
+ diskPriv->blockJobStatus);
+ diskPriv->blockJobStatus = -1;
return 0;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index b69f10f..608eed7 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -412,6 +412,53 @@ qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
}
+static virClassPtr qemuDomainDiskPrivateClass;
+static void qemuDomainDiskPrivateDispose(void *obj);
+
+static int
+qemuDomainDiskPrivateOnceInit(void)
+{
+ qemuDomainDiskPrivateClass = virClassNew(virClassForObject(),
+ "qemuDomainDiskPrivate",
+ sizeof(qemuDomainDiskPrivate),
+ qemuDomainDiskPrivateDispose);
+ if (!qemuDomainDiskPrivateClass)
+ return -1;
+ else
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(qemuDomainDiskPrivate)
+
+static virObjectPtr
+qemuDomainDiskPrivateNew(void)
+{
+ qemuDomainDiskPrivatePtr priv;
+
+ if (qemuDomainDiskPrivateInitialize() < 0)
+ return NULL;
+
+ if (!(priv = virObjectNew(qemuDomainDiskPrivateClass)))
+ return NULL;
+
+ if (virCondInit(&priv->blockJobSyncCond) < 0) {
+ virReportSystemError(errno, "%s", _("Failed to initialize
condition"));
+ virObjectUnref(priv);
+ return NULL;
+ }
+
+ return (virObjectPtr) priv;
+}
+
+static void
+qemuDomainDiskPrivateDispose(void *obj)
+{
+ qemuDomainDiskPrivatePtr priv = obj;
+
+ virCondDestroy(&priv->blockJobSyncCond);
+}
+
+
static void *
qemuDomainObjPrivateAlloc(void)
{
@@ -741,6 +788,7 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = {
.alloc = qemuDomainObjPrivateAlloc,
.free = qemuDomainObjPrivateFree,
+ .diskNew = qemuDomainDiskPrivateNew,
.parse = qemuDomainObjPrivateXMLParse,
.format = qemuDomainObjPrivateXMLFormat,
};
@@ -2809,6 +2857,8 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
bool
qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
{
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+
if (disk->mirror) {
virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
_("disk '%s' already in active block job"),
@@ -2817,7 +2867,7 @@ qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
return true;
}
- if (disk->blockjob) {
+ if (diskPriv->blockjob) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("disk '%s' already in active block job"),
disk->dst);
@@ -2843,12 +2893,13 @@ qemuDomainHasBlockjob(virDomainObjPtr vm,
{
size_t i;
for (i = 0; i < vm->def->ndisks; i++) {
- if (!copy_only &&
- vm->def->disks[i]->blockjob)
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
+
+ if (!copy_only && diskPriv->blockjob)
return true;
- if (vm->def->disks[i]->mirror &&
- vm->def->disks[i]->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
+ if (disk->mirror && disk->mirrorJob ==
VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
return true;
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 7f2e4b5..53df1d3 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -34,6 +34,7 @@
# include "qemu_conf.h"
# include "qemu_capabilities.h"
# include "virchrdev.h"
+# include "virobject.h"
# define QEMU_DOMAIN_FORMAT_LIVE_FLAGS \
(VIR_DOMAIN_XML_SECURE | \
@@ -199,6 +200,26 @@ struct _qemuDomainObjPrivate {
virBitmapPtr autoCpuset;
};
+# define QEMU_DOMAIN_DISK_PRIVATE(disk) \
+ ((qemuDomainDiskPrivatePtr) (disk)->privateData)
+
+typedef struct _qemuDomainDiskPrivate qemuDomainDiskPrivate;
+typedef qemuDomainDiskPrivate *qemuDomainDiskPrivatePtr;
+struct _qemuDomainDiskPrivate {
+ virObject parent;
+
+ /* ideally we want a smarter way to interlock block jobs on single qemu disk
+ * in the future, but for now we just disallow any concurrent job on a
+ * single disk */
+ bool blockjob;
+
+ /* for some synchronous block jobs, we need to notify the owner */
+ virCond blockJobSyncCond;
+ int blockJobType; /* type of the block job from the event */
+ int blockJobStatus; /* status of the finished block job */
+ bool blockJobSync; /* the block job needs synchronized termination */
+};
+
typedef enum {
QEMU_PROCESS_EVENT_WATCHDOG = 0,
QEMU_PROCESS_EVENT_GUESTPANIC,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c54199c..9344533 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -14315,9 +14315,10 @@ qemuDomainSnapshotPrepare(virConnectPtr conn,
for (i = 0; i < def->ndisks; i++) {
virDomainSnapshotDiskDefPtr disk = &def->disks[i];
virDomainDiskDefPtr dom_disk = vm->def->disks[i];
+ qemuDomainDiskPrivatePtr dom_diskPriv = QEMU_DOMAIN_DISK_PRIVATE(dom_disk);
if (disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE &&
- dom_disk->blockjob) {
+ dom_diskPriv->blockjob) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("disk '%s' has an active block job"),
disk->name);
@@ -16637,7 +16638,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
if (ret < 0)
goto endjob;
- disk->blockjob = true;
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
endjob:
qemuDomainObjEndJob(driver, vm);
@@ -16765,7 +16766,7 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
}
endjob:
- if (disk && disk->blockJobSync)
+ if (disk && QEMU_DOMAIN_DISK_PRIVATE(disk)->blockJobSync)
qemuBlockJobSyncEnd(driver, vm, disk, NULL);
qemuDomainObjEndJob(driver, vm);
@@ -17098,7 +17099,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
disk->mirror = mirror;
mirror = NULL;
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
- disk->blockjob = true;
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
VIR_WARN("Unable to save status on vm %s after state change",
@@ -17491,7 +17492,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
}
if (ret == 0)
- disk->blockjob = true;
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
if (mirror) {
if (ret == 0) {
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 8f2189b..7472b09 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1743,6 +1743,7 @@ qemuMigrationCheckDriveMirror(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
/* skip shared, RO and source-less disks */
if (disk->src->shared || disk->src->readonly ||
@@ -1750,7 +1751,7 @@ qemuMigrationCheckDriveMirror(virQEMUDriverPtr driver,
continue;
/* skip disks that didn't start mirroring */
- if (!disk->blockJobSync)
+ if (!diskPriv->blockJobSync)
continue;
/* process any pending event */
@@ -1871,6 +1872,7 @@ qemuMigrationCancelDriveMirror(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
+ qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
/* skip shared, RO and source-less disks */
if (disk->src->shared || disk->src->readonly ||
@@ -1878,7 +1880,7 @@ qemuMigrationCancelDriveMirror(virQEMUDriverPtr driver,
continue;
/* skip disks that didn't start mirroring */
- if (!disk->blockJobSync)
+ if (!diskPriv->blockJobSync)
continue;
if (qemuMigrationCancelOneDriveMirror(driver, vm, disk) < 0)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 56719eb..2b3d9b5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1001,6 +1001,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virQEMUDriverPtr driver = opaque;
struct qemuProcessEvent *processEvent = NULL;
virDomainDiskDefPtr disk;
+ qemuDomainDiskPrivatePtr diskPriv;
char *data = NULL;
virObjectLock(vm);
@@ -1010,12 +1011,13 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
if (!(disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias)))
goto error;
+ diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
- if (disk->blockJobSync) {
- disk->blockJobType = type;
- disk->blockJobStatus = status;
+ if (diskPriv->blockJobSync) {
+ diskPriv->blockJobType = type;
+ diskPriv->blockJobStatus = status;
/* We have an SYNC API waiting for this event, dispatch it back */
- virCondSignal(&disk->blockJobSyncCond);
+ virCondSignal(&diskPriv->blockJobSyncCond);
} else {
/* there is no waiting SYNC API, dispatch the update to a thread */
if (VIR_ALLOC(processEvent) < 0)
@@ -5063,9 +5065,10 @@ void qemuProcessStop(virQEMUDriverPtr driver,
/* Wake up anything waiting on synchronous block jobs */
for (i = 0; i < vm->def->ndisks; i++) {
- virDomainDiskDefPtr disk = vm->def->disks[i];
- if (disk->blockJobSync && disk->blockJobStatus == -1)
- virCondSignal(&disk->blockJobSyncCond);
+ qemuDomainDiskPrivatePtr diskPriv =
+ QEMU_DOMAIN_DISK_PRIVATE(vm->def->disks[i]);
+ if (diskPriv->blockJobSync && diskPriv->blockJobStatus == -1)
+ virCondSignal(&diskPriv->blockJobSyncCond);
}
if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0) {
--
2.4.0