On 2012年12月12日 11:35, Osier Yang wrote:
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).
Ah, sorry, the correct diff is:
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list