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