!(ret->privateData = xmlopt->privateData.diskNew()))
goto error;
- if (virCondInit(&ret->blockJobSyncCond) < 0) {
- virReportSystemError(errno, "%s", _("Failed to initialize condition"));
- goto error;
- }
-
return ret;
error:
VIR_FREE(def->domain_name);
virDomainDeviceInfoClear(&def->info);
virObjectUnref(def->privateData);
- virCondDestroy(&def->blockJobSyncCond);
VIR_FREE(def);
}
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;
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 */
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:
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:
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;
}
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;
}
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) {
_("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;
}
if (r < 0) {
- disk->blockJobSync = false;
+ diskPriv->blockJobSync = false;
virReportSystemError(errno, "%s",
_("Unable to wait on block job sync "
"condition"));
}
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;
}
}
+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)
{
virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = {
.alloc = qemuDomainObjPrivateAlloc,
.free = qemuDomainObjPrivateFree,
+ .diskNew = qemuDomainDiskPrivateNew,
.parse = qemuDomainObjPrivateXMLParse,
.format = qemuDomainObjPrivateXMLFormat,
};
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"),
return true;
}
- if (disk->blockjob) {
+ if (diskPriv->blockjob) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("disk '%s' already in active block job"),
disk->dst);
{
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;
}
# include "qemu_conf.h"
# include "qemu_capabilities.h"
# include "virchrdev.h"
+# include "virobject.h"
# define QEMU_DOMAIN_FORMAT_LIVE_FLAGS \
(VIR_DOMAIN_XML_SECURE | \
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,
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);
if (ret < 0)
goto endjob;
- disk->blockjob = true;
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
endjob:
qemuDomainObjEndJob(driver, vm);
}
endjob:
- if (disk && disk->blockJobSync)
+ if (disk && QEMU_DOMAIN_DISK_PRIVATE(disk)->blockJobSync)
qemuBlockJobSyncEnd(driver, vm, disk, NULL);
qemuDomainObjEndJob(driver, 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",
}
if (ret == 0)
- disk->blockjob = true;
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
if (mirror) {
if (ret == 0) {
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 ||
continue;
/* skip disks that didn't start mirroring */
- if (!disk->blockJobSync)
+ if (!diskPriv->blockJobSync)
continue;
/* process any pending event */
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 ||
continue;
/* skip disks that didn't start mirroring */
- if (!disk->blockJobSync)
+ if (!diskPriv->blockJobSync)
continue;
if (qemuMigrationCancelOneDriveMirror(driver, vm, disk) < 0)
virQEMUDriverPtr driver = opaque;
struct qemuProcessEvent *processEvent = NULL;
virDomainDiskDefPtr disk;
+ qemuDomainDiskPrivatePtr diskPriv;
char *data = NULL;
virObjectLock(vm);
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)
/* 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) {