virHashForEach(driver->closeCallbacks, qemuDriverCloseCallbackRun, &data);
}
+
+/* Construct the hash key for sharedDisks as "major:minor" */
+char *
+qemuGetSharedDiskKey(const char *disk_path)
+{
+ int maj, min;
+ char *key = NULL;
+ int rc;
+
+ if ((rc = virGetDeviceID(disk_path, &maj, &min)) < 0) {
+ virReportSystemError(-rc,
+ _("Unable to get minor number of device '%s'"),
+ disk_path);
+ return NULL;
+ }
+
+ if (virAsprintf(&key, "%d:%d", maj, min) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ return key;
+}
+
+/* Increase ref count if the entry already exists, otherwise
+ * add a new entry.
+ */
+int
+qemuAddSharedDisk(virHashTablePtr sharedDisks,
+ const char *disk_path)
+{
+ size_t *ref = NULL;
+ char *key = NULL;
+
+ if (!(key = qemuGetSharedDiskKey(disk_path)))
+ return -1;
+
+ if ((ref = virHashLookup(sharedDisks, key))) {
+ if (virHashUpdateEntry(sharedDisks, key, ++ref) < 0) {
+ VIR_FREE(key);
+ return -1;
+ }
+ } else {
+ if (virHashAddEntry(sharedDisks, key, (void *)0x1)) {
+ VIR_FREE(key);
+ return -1;
+ }
+ }
+
+ VIR_FREE(key);
+ return 0;
+}
+
+/* Decrease the ref count if the entry already exists, otherwise
+ * remove the entry.
+ */
+int
+qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
+ const char *disk_path)
+{
+ size_t *ref = NULL;
+ char *key = NULL;
+
+ if (!(key = qemuGetSharedDiskKey(disk_path)))
+ return -1;
+
+ if (!(ref = virHashLookup(sharedDisks, key))) {
+ VIR_FREE(key);
+ return -1;
+ }
+
+ if (ref != (void *)0x1) {
+ if (virHashUpdateEntry(sharedDisks, key, --ref) < 0) {
+ VIR_FREE(key);
+ return -1;
+ }
+ } else {
+ if (virHashRemoveEntry(sharedDisks, key) < 0) {
+ VIR_FREE(key);
+ return -1;
+ }
+ }
+
+ VIR_FREE(key);
+ return 0;
+}
/* The devices which is are not in use by the host or any guest. */
pciDeviceList *inactivePciHostdevs;
+ virHashTablePtr sharedDisks;
+
virBitmapPtr reservedRemotePorts;
virSysinfoDefPtr hostsysinfo;
void qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
virConnectPtr conn);
+int qemuAddSharedDisk(virHashTablePtr sharedDisks,
+ const char *disk_path)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
+ const char *disk_path)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+char * qemuGetSharedDiskKey(const char *disk_path)
+ ATTRIBUTE_NONNULL(1);
+
#endif /* __QEMUD_CONF_H */
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,
pciDeviceListFree(qemu_driver->activePciHostdevs);
pciDeviceListFree(qemu_driver->inactivePciHostdevs);
usbDeviceListFree(qemu_driver->activeUsbHostdevs);
+ virHashFree(qemu_driver->sharedDisks);
virCapabilitiesFree(qemu_driver->caps);
qemuCapsCacheFree(qemu_driver->capsCache);
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(disk->src));
}
+
+ if (ret == 0 &&
+ disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
+ disk->shared) {
+ if (qemuAddSharedDisk(driver->sharedDisks, disk->src) < 0)
+ VIR_WARN("Failed to add disk '%s' to shared disk table",
+ disk->src);
+ }
+
end:
if (cgroup)
virCgroupFree(&cgroup);
virDomainDiskDeviceTypeToString(disk->type));
break;
}
+
+ if (ret == 0 &&
+ disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
+ disk->shared) {
+ if (qemuRemoveSharedDisk(driver->sharedDisks, disk->src) < 0)
+ VIR_WARN("Failed to remove disk '%s' from shared disk table",
+ disk->src);
+ }
+
return ret;
}
/* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */
for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = vm->def->disks[i];
+
if (vm->def->disks[i]->rawio == 1)
#ifdef CAP_SYS_RAWIO
virCommandAllowCap(cmd, CAP_SYS_RAWIO);
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Raw I/O is not supported on this platform"));
#endif
+
+ if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK && disk->shared) {
+ if (qemuAddSharedDisk(driver->sharedDisks, disk->src) < 0)
+ goto cleanup;
+ }
}
virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
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->type == VIR_DOMAIN_DISK_TYPE_BLOCK && 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) {