1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

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())) !(ret->privateData = xmlopt->privateData.diskNew()))
goto error; goto error;
if (virCondInit(&ret->blockJobSyncCond) < 0) {
virReportSystemError(errno, "%s", _("Failed to initialize condition"));
goto error;
}
return ret; return ret;
error: error:
@ -1319,7 +1314,6 @@ virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->domain_name); VIR_FREE(def->domain_name);
virDomainDeviceInfoClear(&def->info); virDomainDeviceInfoClear(&def->info);
virObjectUnref(def->privateData); virObjectUnref(def->privateData);
virCondDestroy(&def->blockJobSyncCond);
VIR_FREE(def); VIR_FREE(def);
} }

View File

@ -691,20 +691,10 @@ struct _virDomainDiskDef {
int tray_status; /* enum virDomainDiskTray */ int tray_status; /* enum virDomainDiskTray */
int removable; /* enum virTristateSwitch */ 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; virStorageSourcePtr mirror;
int mirrorState; /* enum virDomainDiskMirrorState */ int mirrorState; /* enum virDomainDiskMirrorState */
int mirrorJob; /* virDomainBlockJobType */ 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 { struct {
unsigned int cylinders; unsigned int cylinders;
unsigned int heads; unsigned int heads;

View File

@ -65,6 +65,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virDomainDiskDefPtr persistDisk = NULL; virDomainDiskDefPtr persistDisk = NULL;
bool save = false; bool save = false;
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
/* Have to generate two variants of the event for old vs. new /* Have to generate two variants of the event for old vs. new
* client callbacks */ * client callbacks */
@ -127,7 +128,7 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
true, true)); true, true));
disk->blockjob = false; diskPriv->blockjob = false;
break; break;
case VIR_DOMAIN_BLOCK_JOB_READY: 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; VIR_DOMAIN_DISK_MIRROR_STATE_ABORT : VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
save = true; save = true;
disk->blockjob = false; diskPriv->blockjob = false;
break; break;
case VIR_DOMAIN_BLOCK_JOB_LAST: case VIR_DOMAIN_BLOCK_JOB_LAST:
@ -185,11 +186,13 @@ qemuBlockJobEventProcess(virQEMUDriverPtr driver,
void void
qemuBlockJobSyncBegin(virDomainDiskDefPtr disk) 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", VIR_WARN("Disk %s already has synchronous block job",
disk->dst); disk->dst);
disk->blockJobSync = true; diskPriv->blockJobSync = true;
} }
@ -211,15 +214,17 @@ qemuBlockJobSyncEnd(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk, virDomainDiskDefPtr disk,
virConnectDomainEventBlockJobStatus *ret_status) 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) if (ret_status)
*ret_status = disk->blockJobStatus; *ret_status = diskPriv->blockJobStatus;
qemuBlockJobEventProcess(driver, vm, disk, qemuBlockJobEventProcess(driver, vm, disk,
disk->blockJobType, diskPriv->blockJobType,
disk->blockJobStatus); diskPriv->blockJobStatus);
disk->blockJobStatus = -1; diskPriv->blockJobStatus = -1;
} }
disk->blockJobSync = false; diskPriv->blockJobSync = false;
} }
@ -248,24 +253,26 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
unsigned long long timeout, unsigned long long timeout,
virConnectDomainEventBlockJobStatus *ret_status) virConnectDomainEventBlockJobStatus *ret_status)
{ {
if (!disk->blockJobSync) { qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
if (!diskPriv->blockJobSync) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No current synchronous block job")); _("No current synchronous block job"));
return -1; return -1;
} }
while (disk->blockJobSync && disk->blockJobStatus == -1) { while (diskPriv->blockJobSync && diskPriv->blockJobStatus == -1) {
int r; int r;
if (!virDomainObjIsActive(vm)) { if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit")); _("guest unexpectedly quit"));
disk->blockJobSync = false; diskPriv->blockJobSync = false;
return -1; return -1;
} }
if (timeout == (unsigned long long)-1) { if (timeout == (unsigned long long)-1) {
r = virCondWait(&disk->blockJobSyncCond, &vm->parent.lock); r = virCondWait(&diskPriv->blockJobSyncCond, &vm->parent.lock);
} else if (timeout) { } else if (timeout) {
unsigned long long now; unsigned long long now;
if (virTimeMillisNow(&now) < 0) { if (virTimeMillisNow(&now) < 0) {
@ -273,7 +280,8 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
_("Unable to get current time")); _("Unable to get current time"));
return -1; return -1;
} }
r = virCondWaitUntil(&disk->blockJobSyncCond, &vm->parent.lock, r = virCondWaitUntil(&diskPriv->blockJobSyncCond,
&vm->parent.lock,
now + timeout); now + timeout);
if (r < 0 && errno == ETIMEDOUT) if (r < 0 && errno == ETIMEDOUT)
return 0; return 0;
@ -283,7 +291,7 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
} }
if (r < 0) { if (r < 0) {
disk->blockJobSync = false; diskPriv->blockJobSync = false;
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("Unable to wait on block job sync " _("Unable to wait on block job sync "
"condition")); "condition"));
@ -292,11 +300,11 @@ qemuBlockJobSyncWaitWithTimeout(virQEMUDriverPtr driver,
} }
if (ret_status) if (ret_status)
*ret_status = disk->blockJobStatus; *ret_status = diskPriv->blockJobStatus;
qemuBlockJobEventProcess(driver, vm, disk, qemuBlockJobEventProcess(driver, vm, disk,
disk->blockJobType, diskPriv->blockJobType,
disk->blockJobStatus); diskPriv->blockJobStatus);
disk->blockJobStatus = -1; diskPriv->blockJobStatus = -1;
return 0; 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 * static void *
qemuDomainObjPrivateAlloc(void) qemuDomainObjPrivateAlloc(void)
{ {
@ -741,6 +788,7 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = { virDomainXMLPrivateDataCallbacks virQEMUDriverPrivateDataCallbacks = {
.alloc = qemuDomainObjPrivateAlloc, .alloc = qemuDomainObjPrivateAlloc,
.free = qemuDomainObjPrivateFree, .free = qemuDomainObjPrivateFree,
.diskNew = qemuDomainDiskPrivateNew,
.parse = qemuDomainObjPrivateXMLParse, .parse = qemuDomainObjPrivateXMLParse,
.format = qemuDomainObjPrivateXMLFormat, .format = qemuDomainObjPrivateXMLFormat,
}; };
@ -2809,6 +2857,8 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
bool bool
qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk) qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
{ {
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
if (disk->mirror) { if (disk->mirror) {
virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
_("disk '%s' already in active block job"), _("disk '%s' already in active block job"),
@ -2817,7 +2867,7 @@ qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
return true; return true;
} }
if (disk->blockjob) { if (diskPriv->blockjob) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("disk '%s' already in active block job"), _("disk '%s' already in active block job"),
disk->dst); disk->dst);
@ -2843,12 +2893,13 @@ qemuDomainHasBlockjob(virDomainObjPtr vm,
{ {
size_t i; size_t i;
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
if (!copy_only && virDomainDiskDefPtr disk = vm->def->disks[i];
vm->def->disks[i]->blockjob) qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
if (!copy_only && diskPriv->blockjob)
return true; return true;
if (vm->def->disks[i]->mirror && if (disk->mirror && disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
vm->def->disks[i]->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY)
return true; return true;
} }

View File

@ -34,6 +34,7 @@
# include "qemu_conf.h" # include "qemu_conf.h"
# include "qemu_capabilities.h" # include "qemu_capabilities.h"
# include "virchrdev.h" # include "virchrdev.h"
# include "virobject.h"
# define QEMU_DOMAIN_FORMAT_LIVE_FLAGS \ # define QEMU_DOMAIN_FORMAT_LIVE_FLAGS \
(VIR_DOMAIN_XML_SECURE | \ (VIR_DOMAIN_XML_SECURE | \
@ -199,6 +200,26 @@ struct _qemuDomainObjPrivate {
virBitmapPtr autoCpuset; 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 { typedef enum {
QEMU_PROCESS_EVENT_WATCHDOG = 0, QEMU_PROCESS_EVENT_WATCHDOG = 0,
QEMU_PROCESS_EVENT_GUESTPANIC, QEMU_PROCESS_EVENT_GUESTPANIC,

View File

@ -14317,9 +14317,10 @@ qemuDomainSnapshotPrepare(virConnectPtr conn,
for (i = 0; i < def->ndisks; i++) { for (i = 0; i < def->ndisks; i++) {
virDomainSnapshotDiskDefPtr disk = &def->disks[i]; virDomainSnapshotDiskDefPtr disk = &def->disks[i];
virDomainDiskDefPtr dom_disk = vm->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 && if (disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE &&
dom_disk->blockjob) { dom_diskPriv->blockjob) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("disk '%s' has an active block job"), _("disk '%s' has an active block job"),
disk->name); disk->name);
@ -16639,7 +16640,7 @@ qemuDomainBlockPullCommon(virQEMUDriverPtr driver,
if (ret < 0) if (ret < 0)
goto endjob; goto endjob;
disk->blockjob = true; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
endjob: endjob:
qemuDomainObjEndJob(driver, vm); qemuDomainObjEndJob(driver, vm);
@ -16767,7 +16768,7 @@ qemuDomainBlockJobAbort(virDomainPtr dom,
} }
endjob: endjob:
if (disk && disk->blockJobSync) if (disk && QEMU_DOMAIN_DISK_PRIVATE(disk)->blockJobSync)
qemuBlockJobSyncEnd(driver, vm, disk, NULL); qemuBlockJobSyncEnd(driver, vm, disk, NULL);
qemuDomainObjEndJob(driver, vm); qemuDomainObjEndJob(driver, vm);
@ -17100,7 +17101,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
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;
disk->blockjob = true; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 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",
@ -17493,7 +17494,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
} }
if (ret == 0) if (ret == 0)
disk->blockjob = true; QEMU_DOMAIN_DISK_PRIVATE(disk)->blockjob = true;
if (mirror) { if (mirror) {
if (ret == 0) { if (ret == 0) {

View File

@ -1743,6 +1743,7 @@ qemuMigrationCheckDriveMirror(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i]; virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
/* skip shared, RO and source-less disks */ /* skip shared, RO and source-less disks */
if (disk->src->shared || disk->src->readonly || if (disk->src->shared || disk->src->readonly ||
@ -1750,7 +1751,7 @@ qemuMigrationCheckDriveMirror(virQEMUDriverPtr driver,
continue; continue;
/* skip disks that didn't start mirroring */ /* skip disks that didn't start mirroring */
if (!disk->blockJobSync) if (!diskPriv->blockJobSync)
continue; continue;
/* process any pending event */ /* process any pending event */
@ -1871,6 +1872,7 @@ qemuMigrationCancelDriveMirror(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i]; virDomainDiskDefPtr disk = vm->def->disks[i];
qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
/* skip shared, RO and source-less disks */ /* skip shared, RO and source-less disks */
if (disk->src->shared || disk->src->readonly || if (disk->src->shared || disk->src->readonly ||
@ -1878,7 +1880,7 @@ qemuMigrationCancelDriveMirror(virQEMUDriverPtr driver,
continue; continue;
/* skip disks that didn't start mirroring */ /* skip disks that didn't start mirroring */
if (!disk->blockJobSync) if (!diskPriv->blockJobSync)
continue; continue;
if (qemuMigrationCancelOneDriveMirror(driver, vm, disk) < 0) if (qemuMigrationCancelOneDriveMirror(driver, vm, disk) < 0)

View File

@ -1001,6 +1001,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virQEMUDriverPtr driver = opaque; virQEMUDriverPtr driver = opaque;
struct qemuProcessEvent *processEvent = NULL; struct qemuProcessEvent *processEvent = NULL;
virDomainDiskDefPtr disk; virDomainDiskDefPtr disk;
qemuDomainDiskPrivatePtr diskPriv;
char *data = NULL; char *data = NULL;
virObjectLock(vm); virObjectLock(vm);
@ -1010,12 +1011,13 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
if (!(disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias))) if (!(disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias)))
goto error; goto error;
diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
if (disk->blockJobSync) { if (diskPriv->blockJobSync) {
disk->blockJobType = type; diskPriv->blockJobType = type;
disk->blockJobStatus = status; diskPriv->blockJobStatus = status;
/* We have an SYNC API waiting for this event, dispatch it back */ /* We have an SYNC API waiting for this event, dispatch it back */
virCondSignal(&disk->blockJobSyncCond); virCondSignal(&diskPriv->blockJobSyncCond);
} else { } else {
/* there is no waiting SYNC API, dispatch the update to a thread */ /* there is no waiting SYNC API, dispatch the update to a thread */
if (VIR_ALLOC(processEvent) < 0) if (VIR_ALLOC(processEvent) < 0)
@ -5063,9 +5065,10 @@ void qemuProcessStop(virQEMUDriverPtr driver,
/* Wake up anything waiting on synchronous block jobs */ /* Wake up anything waiting on synchronous block jobs */
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i]; qemuDomainDiskPrivatePtr diskPriv =
if (disk->blockJobSync && disk->blockJobStatus == -1) QEMU_DOMAIN_DISK_PRIVATE(vm->def->disks[i]);
virCondSignal(&disk->blockJobSyncCond); if (diskPriv->blockJobSync && diskPriv->blockJobStatus == -1)
virCondSignal(&diskPriv->blockJobSyncCond);
} }
if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0) { if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0) {