On 2012年12月11日 21:37, Osier Yang wrote:
This introduces a hash table for qemu driver, to store the shared disk's info as (@disk_path, {@ref_count, @orig_cdbfilter}). @ref_count is the number of domains which shares the disk. @orig_cdbfilter is the original cdbfilter setting of the shared disk, it will be used to restore the the disk's cdbfilter setting to original value by later patches. * src/qemu/qemu_conf.h: (Add member 'sharedDisks' of type virHashTablePtr; New struct qemuSharedDiskEntry; Declare helpers qemuAddSharedDisk, qemuRemoveSharedDisk) * src/qemu/qemu_conf.c (Implement the two helpers) * src/qemu/qemu_process.c (Update 'sharedDisks' when domain starting and shutdown) * src/qemu/qemu_driver.c (Update 'sharedDisks' when attaching or detaching disk). 0 is passed for orig_cdbfilter temporarily, later patches will update it. --- src/qemu/qemu_conf.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_conf.h | 18 +++++++++++++++++ src/qemu/qemu_driver.c | 17 ++++++++++++++++ src/qemu/qemu_process.c | 17 +++++++++++++++- 4 files changed, 99 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 8d380a1..2b21186 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -556,3 +556,51 @@ qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver, virHashForEach(driver->closeCallbacks, qemuDriverCloseCallbackRun,&data); } + +/* Increase ref count if the entry already exists, otherwise + * add a new entry. + */ +int +qemuAddSharedDisk(virHashTablePtr sharedDisks, + const char *disk_path, + int orig_cdbfilter) +{ + qemuSharedDiskEntryPtr entry = NULL; + + if ((entry = virHashLookup(sharedDisks, disk_path))) { + entry->ref++; + } else { + if (VIR_ALLOC(entry)< 0) + return -1; + + entry->ref = 1; + entry->orig_cdbfilter = orig_cdbfilter; + + if (virHashAddEntry(sharedDisks, disk_path, entry)) + return -1; + } + + return 0; +} + +/* Decrease the ref count if the entry already exists, otherwise + * remove the entry. + */ +int +qemuRemoveSharedDisk(virHashTablePtr sharedDisks, + const char *disk_path) +{ + qemuSharedDiskEntryPtr entry = NULL; + + if (!(entry = virHashLookup(sharedDisks, disk_path))) + return -1; + + if (entry->ref != 1) { + entry->ref--; + } else { + if (virHashRemoveEntry(sharedDisks, disk_path)< 0) + return -1; + } + + return 0; +} diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index d0d25ce..df901f6 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -147,6 +147,8 @@ struct _virQEMUDriver { /* The devices which is are not in use by the host or any guest. */ pciDeviceList *inactivePciHostdevs; + virHashTablePtr sharedDisks; + virBitmapPtr reservedRemotePorts; virSysinfoDefPtr hostsysinfo; @@ -193,6 +195,13 @@ struct qemuDomainDiskInfo { int io_status; }; +typedef struct qemuSharedDiskEntry qemuSharedDiskEntry; +typedef qemuSharedDiskEntry *qemuSharedDiskEntryPtr; +struct qemuSharedDiskEntry { + size_t ref; /* ref count of the shared disk */ + int orig_cdbfilter; /* Original disk's cdbfilter setting */ +}; + typedef virDomainObjPtr (*qemuDriverCloseCallback)(virQEMUDriverPtr driver, virDomainObjPtr vm, virConnectPtr conn); @@ -211,4 +220,13 @@ qemuDriverCloseCallback qemuDriverCloseCallbackGet(virQEMUDriverPtr driver, void qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver, virConnectPtr conn); +int qemuAddSharedDisk(virHashTablePtr sharedDisks, + const char *disk_path, + int orig_cdbfilter) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +int qemuRemoveSharedDisk(virHashTablePtr sharedDisks, + const char *disk_path) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + #endif /* __QEMUD_CONF_H */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e099c5c..fdde74d 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -810,6 +810,9 @@ qemuStartup(bool privileged, if ((qemu_driver->inactivePciHostdevs = pciDeviceListNew()) == NULL) goto error; + if (!(qemu_driver->sharedDisks = virHashCreate(30, NULL))) + goto error; + if (privileged) { if (chown(qemu_driver->libDir, qemu_driver->user, qemu_driver->group)< 0) { virReportSystemError(errno, @@ -1064,6 +1067,7 @@ qemuShutdown(void) { pciDeviceListFree(qemu_driver->activePciHostdevs); pciDeviceListFree(qemu_driver->inactivePciHostdevs); usbDeviceListFree(qemu_driver->activeUsbHostdevs); + virHashFree(qemu_driver->sharedDisks); virCapabilitiesFree(qemu_driver->caps); qemuCapsCacheFree(qemu_driver->capsCache); @@ -6035,6 +6039,12 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, VIR_WARN("Failed to teardown cgroup for disk path %s", NULLSTR(disk->src)); } + + if (ret == 0&& disk->shared) { + if (qemuAddSharedDisk(driver->sharedDisks, disk->src, 0)< 0) + VIR_WARN("Failed to add disk '%s' to shared disk table", + disk->src); + } end: if (cgroup) virCgroupFree(&cgroup); @@ -6149,6 +6159,13 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver, virDomainDiskDeviceTypeToString(disk->type)); break; } + + if (ret == 0&& disk->shared) { + if (qemuRemoveSharedDisk(driver->sharedDisks, disk->src)< 0) + VIR_WARN("Failed to remove disk '%s' from shared disk table", + disk->src); + } + return ret; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ab04599..89152b8 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3706,8 +3706,15 @@ int qemuProcessStart(virConnectPtr conn, /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */ for (i = 0; i< vm->def->ndisks; i++) { - if (vm->def->disks[i]->rawio == 1) + virDomainDiskDefPtr disk = vm->def->disks[i]; + + if (disk->rawio == 1) virCommandAllowCap(cmd, CAP_SYS_RAWIO); + + if (disk->shared) { + if (qemuAddSharedDisk(driver->sharedDisks, disk->src, 0)< 0) + goto cleanup; + } } virCommandSetPreExecHook(cmd, qemuProcessHook,&hookData); @@ -4104,6 +4111,14 @@ void qemuProcessStop(virQEMUDriverPtr driver, flags& VIR_QEMU_PROCESS_STOP_MIGRATED); virSecurityManagerReleaseLabel(driver->securityManager, vm->def); + for (i = 0; i< vm->def->ndisks; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + + if (disk->shared) { + ignore_value(qemuRemoveSharedDisk(driver->sharedDisks, disk->src)); + } + } + /* Clear out dynamically assigned labels */ for (i = 0; i< vm->def->nseclabels; i++) { if (vm->def->seclabels[i]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
With the diff below squashed in: (the dataFree was missed when changing the hash value from only ref count to a struct).
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 48201c1..35ce32e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -603,6 +603,11 @@ qemuDomainFindMaxID(void *payload, *driver_maxid = vm->def->id + 1; } +static void +qemuSharedDiskFree(void *entry, const void *name ATTRIBUTE_UNUSED) +{ + VIR_FREE(entry); +} /** * qemuStartup: @@ -810,7 +815,7 @@ qemuStartup(bool privileged, if ((qemu_driver->inactivePciHostdevs = pciDeviceListNew()) == NULL) goto error; - if (!(qemu_driver->sharedDisks = virHashCreate(30, NULL))) + if (!(qemu_driver->sharedDisks = virHashCreate(30, qemuSharedDiskFree))) goto error; if (privileged) { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ba777e2..1e09cab 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3405,9 +3405,9 @@ qemuCheckSharedDisk(virHashTablePtr sharedDisks, return -1; if ((val == 0 && - disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES) || + disk->cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES) || (val == 1 && - disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_NO)) + disk->cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_NO)) return 0; virReportError(VIR_ERR_INTERNAL_ERROR, @@ -3748,7 +3748,6 @@ int qemuProcessStart(virConnectPtr conn, if (disk->rawio == 1) virCommandAllowCap(cmd, CAP_SYS_RAWIO); - /* Set sysfs unpriv_sgio if cdbfilter is specified */ if (disk->cdbfilter) { if (virGetDeviceUnprivSGIO(disk->src, &val) < 0) goto cleanup; @@ -3757,12 +3756,6 @@ int qemuProcessStart(virConnectPtr conn, disk->orig_cdbfilter = VIR_DOMAIN_DISK_CDB_FILTER_YES; else disk->orig_cdbfilter = VIR_DOMAIN_DISK_CDB_FILTER_NO; - - if (virSetDeviceUnprivSGIO(disk->src, - (disk->cdbfilter == - VIR_DOMAIN_DISK_CDB_FILTER_NO) - ? 1 : 0) < 0) - goto cleanup; } if (disk->shared) { @@ -3778,6 +3771,15 @@ int qemuProcessStart(virConnectPtr conn, if (qemuCheckSharedDisk(driver->sharedDisks, disk) < 0) goto cleanup; } + + /* Set sysfs unpriv_sgio if cdbfilter is specified */ + if (disk->cdbfilter) { + if (virSetDeviceUnprivSGIO(disk->src, + (disk->cdbfilter == + VIR_DOMAIN_DISK_CDB_FILTER_NO) + ? 1 : 0) < 0) + goto cleanup; + } } virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list