Move QEMU-only fields from virDomainDiskDef into privateData

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
Jiri Denemark 2015-05-13 11:20:36 +02:00
parent 078717e151
commit 46a7a49535
8 changed files with 125 additions and 55 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -14317,9 +14317,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);
@ -16639,7 +16640,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
if (ret < 0)
goto endjob;
disk->blockjob = true;
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
endjob:
qemuDomainObjEndJob(driver, vm);
@ -16767,7 +16768,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);
@ -17100,7 +17101,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",
@ -17493,7 +17494,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
}
if (ret == 0)
disk->blockjob = true;
QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
if (mirror) {
if (ret == 0) {

View File

@ -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)

View File

@ -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) {