mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 12:35:17 +00:00
qemu: Add a hash table for the shared disks
This introduces a hash table for qemu driver, to store the shared disk's info as (@major:minor, @ref_count). @ref_count is the number of domains which shares the disk. Since we only care about if the disk support unprivileged SG_IO commands, and the SG_IO commands only make sense for block disk, this patch only manages (add/remove hash entry) the shared disk for block disk. * src/qemu/qemu_conf.h: (Add member 'sharedDisks' of type virHashTablePtr; Declare helpers qemuGetSharedDiskKey, qemuAddSharedDisk and qemuRemoveSharedDisk) * src/qemu/qemu_conf.c (Implement the 3 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).
This commit is contained in:
parent
ba72cb12fa
commit
d7ead3e19a
@ -552,3 +552,89 @@ qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -148,6 +148,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;
|
||||
@ -212,4 +214,14 @@ qemuDriverCloseCallback qemuDriverCloseCallbackGet(virQEMUDriverPtr driver,
|
||||
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 */
|
||||
|
@ -843,6 +843,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,
|
||||
@ -1096,6 +1099,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);
|
||||
|
||||
@ -5860,6 +5864,15 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
|
||||
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);
|
||||
@ -5974,6 +5987,15 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -3744,6 +3744,8 @@ 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++) {
|
||||
virDomainDiskDefPtr disk = vm->def->disks[i];
|
||||
|
||||
if (vm->def->disks[i]->rawio == 1)
|
||||
#ifdef CAP_SYS_RAWIO
|
||||
virCommandAllowCap(cmd, CAP_SYS_RAWIO);
|
||||
@ -3751,6 +3753,11 @@ int qemuProcessStart(virConnectPtr conn,
|
||||
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);
|
||||
@ -4147,6 +4154,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->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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user