提交 aeda1ff1 编写于 作者: O Osier Yang

qemu: Refactor the helpers to track shared scsi host device

This changes the helpers qemu{Add,Remove}SharedDisk into
qemu{Add,Remove}SharedDevice, as most of the code in the helpers
can be reused for scsi host device.

To track the shared scsi host device, first it finds out the
device path (e.g. /dev/s[dr]*) which is mapped to the sg device,
and use device ID of the found device path (/dev/s[dr]*) as the
hash key. This is because of the device ID is not unique between
between /dev/s[dr]* and /dev/sg*, e.g.

% sg_map
/dev/sg0  /dev/sda
/dev/sg1  /dev/sr0

% ls -l /dev/sda
brw-rw----. 1 root disk 8, 0 May  2 19:26 /dev/sda

%ls -l /dev/sg0
crw-rw----. 1 root disk 21, 0 May  2 19:26 /dev/sg0
上级 28d3ad95
...@@ -1116,47 +1116,80 @@ cleanup: ...@@ -1116,47 +1116,80 @@ cleanup:
return NULL; return NULL;
} }
/* qemuAddSharedDisk: /* qemuAddSharedDevice:
* @driver: Pointer to qemu driver struct * @driver: Pointer to qemu driver struct
* @disk: The disk def * @dev: The device def
* @name: The domain name * @name: The domain name
* *
* Increase ref count and add the domain name into the list which * Increase ref count and add the domain name into the list which
* records all the domains that use the shared disk if the entry * records all the domains that use the shared device if the entry
* already exists, otherwise add a new entry. * already exists, otherwise add a new entry.
*/ */
int int
qemuAddSharedDisk(virQEMUDriverPtr driver, qemuAddSharedDevice(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk, virDomainDeviceDefPtr dev,
const char *name) const char *name)
{ {
qemuSharedDeviceEntry *entry = NULL; qemuSharedDeviceEntry *entry = NULL;
qemuSharedDeviceEntry *new_entry = NULL; qemuSharedDeviceEntry *new_entry = NULL;
virDomainDiskDefPtr disk = NULL;
virDomainHostdevDefPtr hostdev = NULL;
char *dev_name = NULL;
char *dev_path = NULL;
char *key = NULL; char *key = NULL;
int ret = -1; int ret = -1;
/* Currently the only conflicts we have to care about /* Currently the only conflicts we have to care about for
* for the shared disk is "sgio" setting, which is only * the shared disk and shared host device is "sgio" setting,
* valid for block disk. * which is only valid for block disk and scsi host device.
*/ */
if (!disk->shared || if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
disk = dev->data.disk;
if (disk->shared ||
!disk->src || !disk->src ||
(disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
!(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME &&
disk->srcpool && disk->srcpool &&
disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
return 0; return 0;
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
hostdev = dev->data.hostdev;
if (!hostdev->shareable ||
!(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
return 0;
} else {
return 0;
}
qemuDriverLock(driver); qemuDriverLock(driver);
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0) if (qemuCheckSharedDisk(driver->sharedDevices, disk) < 0)
goto cleanup; goto cleanup;
if (!(key = qemuGetSharedDeviceKey(disk->src))) if (!(key = qemuGetSharedDeviceKey(disk->src)))
goto cleanup; goto cleanup;
} else {
if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
hostdev->source.subsys.u.scsi.bus,
hostdev->source.subsys.u.scsi.target,
hostdev->source.subsys.u.scsi.unit)))
goto cleanup;
if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0) {
virReportOOMError();
goto cleanup;
}
if (!(key = qemuGetSharedDeviceKey(dev_path)))
goto cleanup;
}
if ((entry = virHashLookup(driver->sharedDevices, key))) { if ((entry = virHashLookup(driver->sharedDevices, key))) {
/* Nothing to do if the shared disk is already recorded /* Nothing to do if the shared scsi host device is already
* in the table. * recorded in the table.
*/ */
if (qemuSharedDeviceEntryDomainExists(entry, name, NULL)) { if (qemuSharedDeviceEntryDomainExists(entry, name, NULL)) {
ret = 0; ret = 0;
...@@ -1195,30 +1228,39 @@ qemuAddSharedDisk(virQEMUDriverPtr driver, ...@@ -1195,30 +1228,39 @@ qemuAddSharedDisk(virQEMUDriverPtr driver,
ret = 0; ret = 0;
cleanup: cleanup:
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
VIR_FREE(dev_name);
VIR_FREE(dev_path);
VIR_FREE(key); VIR_FREE(key);
return ret; return ret;
} }
/* qemuRemoveSharedDisk: /* qemuRemoveSharedDevice:
* @driver: Pointer to qemu driver struct * @driver: Pointer to qemu driver struct
* @disk: The disk def * @device: The device def
* @name: The domain name * @name: The domain name
* *
* Decrease ref count and remove the domain name from the list which * Decrease ref count and remove the domain name from the list which
* records all the domains that use the shared disk if ref is not 1, * records all the domains that use the shared device if ref is not
* otherwise remove the entry. * 1, otherwise remove the entry.
*/ */
int int
qemuRemoveSharedDisk(virQEMUDriverPtr driver, qemuRemoveSharedDevice(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk, virDomainDeviceDefPtr dev,
const char *name) const char *name)
{ {
qemuSharedDeviceEntryPtr entry = NULL; qemuSharedDeviceEntryPtr entry = NULL;
qemuSharedDeviceEntryPtr new_entry = NULL; qemuSharedDeviceEntryPtr new_entry = NULL;
virDomainDiskDefPtr disk = NULL;
virDomainHostdevDefPtr hostdev = NULL;
char *key = NULL; char *key = NULL;
char *dev_name = NULL;
char *dev_path = NULL;
int ret = -1; int ret = -1;
int idx; int idx;
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
disk = dev->data.disk;
if (!disk->shared || if (!disk->shared ||
!disk->src || !disk->src ||
(disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK &&
...@@ -1226,10 +1268,37 @@ qemuRemoveSharedDisk(virQEMUDriverPtr driver, ...@@ -1226,10 +1268,37 @@ qemuRemoveSharedDisk(virQEMUDriverPtr driver,
disk->srcpool && disk->srcpool &&
disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK)))
return 0; return 0;
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
hostdev = dev->data.hostdev;
if (!hostdev->shareable ||
!(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI))
return 0;
} else {
return 0;
}
qemuDriverLock(driver); qemuDriverLock(driver);
if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
if (!(key = qemuGetSharedDeviceKey(disk->src))) if (!(key = qemuGetSharedDeviceKey(disk->src)))
goto cleanup; goto cleanup;
} else {
if (!(dev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter,
hostdev->source.subsys.u.scsi.bus,
hostdev->source.subsys.u.scsi.target,
hostdev->source.subsys.u.scsi.unit)))
goto cleanup;
if (virAsprintf(&dev_path, "/dev/%s", dev_name) < 0) {
virReportOOMError();
goto cleanup;
}
if (!(key = qemuGetSharedDeviceKey(dev_path)))
goto cleanup;
}
if (!(entry = virHashLookup(driver->sharedDevices, key))) if (!(entry = virHashLookup(driver->sharedDevices, key)))
goto cleanup; goto cleanup;
...@@ -1265,6 +1334,8 @@ qemuRemoveSharedDisk(virQEMUDriverPtr driver, ...@@ -1265,6 +1334,8 @@ qemuRemoveSharedDisk(virQEMUDriverPtr driver,
ret = 0; ret = 0;
cleanup: cleanup:
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
VIR_FREE(dev_name);
VIR_FREE(dev_path);
VIR_FREE(key); VIR_FREE(key);
return ret; return ret;
} }
......
...@@ -289,22 +289,22 @@ bool qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntryPtr entry, ...@@ -289,22 +289,22 @@ bool qemuSharedDeviceEntryDomainExists(qemuSharedDeviceEntryPtr entry,
int *index) int *index)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuAddSharedDisk(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk,
const char *name)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuRemoveSharedDisk(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk,
const char *name)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
char * qemuGetSharedDeviceKey(const char *disk_path) char * qemuGetSharedDeviceKey(const char *disk_path)
ATTRIBUTE_NONNULL(1); ATTRIBUTE_NONNULL(1);
void qemuSharedDeviceEntryFree(void *payload, const void *name) void qemuSharedDeviceEntryFree(void *payload, const void *name)
ATTRIBUTE_NONNULL(1); ATTRIBUTE_NONNULL(1);
int qemuAddSharedDevice(virQEMUDriverPtr driver,
virDomainDeviceDefPtr dev,
const char *name)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuRemoveSharedDevice(virQEMUDriverPtr driver,
virDomainDeviceDefPtr dev,
const char *name)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int qemuDriverAllocateID(virQEMUDriverPtr driver); int qemuDriverAllocateID(virQEMUDriverPtr driver);
virDomainXMLOptionPtr virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver); virDomainXMLOptionPtr virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver);
......
...@@ -5731,7 +5731,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, ...@@ -5731,7 +5731,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
if (qemuTranslateDiskSourcePool(conn, disk) < 0) if (qemuTranslateDiskSourcePool(conn, disk) < 0)
goto end; goto end;
if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0) if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
goto end; goto end;
if (qemuSetUnprivSGIO(disk) < 0) if (qemuSetUnprivSGIO(disk) < 0)
...@@ -5777,7 +5777,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, ...@@ -5777,7 +5777,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
* if the operation is either ejecting or updating. * if the operation is either ejecting or updating.
*/ */
if (ret == 0) if (ret == 0)
ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk, ignore_value(qemuRemoveSharedDevice(driver, dev_copy,
vm->def->name)); vm->def->name));
break; break;
case VIR_DOMAIN_DISK_DEVICE_DISK: case VIR_DOMAIN_DISK_DEVICE_DISK:
...@@ -5815,7 +5815,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, ...@@ -5815,7 +5815,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
end: end:
if (ret != 0) if (ret != 0)
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name)); ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
virObjectUnref(caps); virObjectUnref(caps);
virDomainDeviceDefFree(dev_copy); virDomainDeviceDefFree(dev_copy);
return ret; return ret;
...@@ -5931,7 +5931,7 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver, ...@@ -5931,7 +5931,7 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
} }
if (ret == 0) if (ret == 0)
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name)); ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
return ret; return ret;
} }
...@@ -6038,7 +6038,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn, ...@@ -6038,7 +6038,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
dev->data.disk = tmp; dev->data.disk = tmp;
/* Add the new disk src into shared disk hash table */ /* Add the new disk src into shared disk hash table */
if (qemuAddSharedDisk(driver, dev->data.disk, vm->def->name) < 0) if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
goto end; goto end;
ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force); ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force);
...@@ -6051,7 +6051,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn, ...@@ -6051,7 +6051,7 @@ qemuDomainChangeDiskMediaLive(virConnectPtr conn,
*/ */
if (ret == 0) { if (ret == 0) {
dev->data.disk = NULL; dev->data.disk = NULL;
ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk, ignore_value(qemuRemoveSharedDevice(driver, dev_copy,
vm->def->name)); vm->def->name));
} }
break; break;
......
...@@ -2982,10 +2982,14 @@ qemuProcessReconnect(void *opaque) ...@@ -2982,10 +2982,14 @@ qemuProcessReconnect(void *opaque)
* qemu_driver->sharedDevices. * qemu_driver->sharedDevices.
*/ */
for (i = 0; i < obj->def->ndisks; i++) { for (i = 0; i < obj->def->ndisks; i++) {
virDomainDeviceDef dev;
if (qemuTranslateDiskSourcePool(conn, obj->def->disks[i]) < 0) if (qemuTranslateDiskSourcePool(conn, obj->def->disks[i]) < 0)
goto error; goto error;
if (qemuAddSharedDisk(driver, obj->def->disks[i],
obj->def->name) < 0) dev.type = VIR_DOMAIN_DEVICE_DISK;
dev.data.disk = obj->def->disks[i];
if (qemuAddSharedDevice(driver, &dev, obj->def->name) < 0)
goto error; goto error;
} }
...@@ -3686,6 +3690,7 @@ int qemuProcessStart(virConnectPtr conn, ...@@ -3686,6 +3690,7 @@ int qemuProcessStart(virConnectPtr conn,
/* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */ /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
virDomainDeviceDef dev;
virDomainDiskDefPtr disk = vm->def->disks[i]; virDomainDiskDefPtr disk = vm->def->disks[i];
if (vm->def->disks[i]->rawio == 1) if (vm->def->disks[i]->rawio == 1)
...@@ -3696,7 +3701,9 @@ int qemuProcessStart(virConnectPtr conn, ...@@ -3696,7 +3701,9 @@ int qemuProcessStart(virConnectPtr conn,
_("Raw I/O is not supported on this platform")); _("Raw I/O is not supported on this platform"));
#endif #endif
if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0) dev.type = VIR_DOMAIN_DEVICE_DISK;
dev.data.disk = disk;
if (qemuAddSharedDevice(driver, &dev, vm->def->name) < 0)
goto cleanup; goto cleanup;
if (qemuSetUnprivSGIO(disk) < 0) if (qemuSetUnprivSGIO(disk) < 0)
...@@ -4107,8 +4114,12 @@ void qemuProcessStop(virQEMUDriverPtr driver, ...@@ -4107,8 +4114,12 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virSecurityManagerReleaseLabel(driver->securityManager, vm->def); virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
for (i = 0; i < vm->def->ndisks; i++) { for (i = 0; i < vm->def->ndisks; i++) {
virDomainDeviceDef dev;
virDomainDiskDefPtr disk = vm->def->disks[i]; virDomainDiskDefPtr disk = vm->def->disks[i];
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
dev.type = VIR_DOMAIN_DEVICE_DISK;
dev.data.disk = disk;
ignore_value(qemuRemoveSharedDevice(driver, &dev, vm->def->name));
} }
/* Clear out dynamically assigned labels */ /* Clear out dynamically assigned labels */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册